@@ -108,7 +108,7 @@ int tfd = -1; /* Traffic log file descript
108108int main (int argc , char * argv []) {
109109/* Usage:
110110Usage:
111- ts-warp -T IP:Port -S IP:Port -H IP:Port -c file.ini -l file.log -v 0-4 -t file.act -d -p file.pid -f -u user -h
111+ ts-warp -T IP:Port -S IP:Port -H IP:Port -c file.ini -l file.log -v 0-4 -t file.act -d -p file.pid -f -u user -D - h
112112
113113Version:
114114 TS-Warp-X.Y.Z
@@ -127,6 +127,7 @@ All parameters are optional:
127127 -f Force start
128128
129129 -u user A user to run ts-warp, default: nobody
130+ -D Do not try spoofing Deep Packet Inspections
130131
131132 -h This message */
132133
@@ -141,6 +142,9 @@ All parameters are optional:
141142 int l_flg = 0 ; /* User didn't set the log file */
142143 int d_flg = 0 ; /* Daemon mode */
143144 int f_flg = 0 ; /* Force start */
145+ int sdpi = 1 ; /* Try bypassing DPI */
146+ /* According to https://github.com/xvzc/SpoofDPI?tab=readme-ov-file#https sending the first 1 byte of a request
147+ to the server, and then sending the rest of the data can help to bypass Deep Packet Inspections of HTTPS */
144148
145149 char * runas_user = RUNAS_USER ; /* A user to run ts-warp */
146150
@@ -177,7 +181,7 @@ All parameters are optional:
177181 #endif
178182
179183
180- while ((flg = getopt (argc , argv , "T:S:H:c:l:v:t:dp:fu:h " )) != -1 )
184+ while ((flg = getopt (argc , argv , "T:S:H:c:l:v:t:dp:fu:Dh " )) != -1 )
181185 switch (flg ) {
182186 case 'T' : /* Internal Transparent server IP/name */
183187 taddr = strsep (& optarg , ":" ); /* IP:PORT */
@@ -233,6 +237,10 @@ All parameters are optional:
233237 #endif
234238 break ;
235239
240+ case 'D' :
241+ sdpi = 0 ;
242+ break ;
243+
236244 case 'h' : /* Help */
237245 default :
238246 (void )usage (0 );
@@ -268,7 +276,9 @@ All parameters are optional:
268276 if (mkfifo (tfile_name , S_IFIFO |S_IRWXU |S_IRGRP |S_IROTH ) == -1 && errno != EEXIST )
269277 printl (LOG_WARN , "Unable to create active connections and traffic log pipe: [%s]" , tfile_name );
270278 else {
271- chown (tfile_name , pwd ? pwd -> pw_uid : 0 , pwd ? pwd -> pw_gid : 0 );
279+ if (chown (tfile_name , pwd ? pwd -> pw_uid : 0 , pwd ? pwd -> pw_gid : 0 ) == -1 )
280+ printl (LOG_WARN , "Unable change owner of the ACT log pipe[%s]" , tfile_name );
281+
272282 if ((tfd = open (tfile_name , O_RDWR ) ) == -1 )
273283 printl (LOG_WARN , "Unable to open active connections and traffic log pipe: [%s]" , tfile_name );
274284 else
@@ -577,21 +587,23 @@ All parameters are optional:
577587 memset (& daddr .ip_addr , 0 , daddr_len );
578588 memset (& daddr .name , 0 , sizeof (daddr .name ) - 1 );
579589
580- #if defined(linux )
581- /* On Linux && nftabeles/iptables */
582- memset (& daddr .ip_addr , 0 , daddr_len );
583- daddr .ip_addr .ss_family = caddr .ss_family ;
584- ret = getsockopt (csock , SOL_IP , SO_ORIGINAL_DST , & daddr .ip_addr , & daddr_len );
585- #else
586- /* On *BSD with PF */
587- ret = nat_lookup (pfd , & caddr , (struct sockaddr_storage * )tres -> ai_addr , & daddr .ip_addr );
588- #endif
589- if (ret ) {
590- printl (LOG_WARN , "Failed to find the real destination IP, trying to get it from the socket" );
591- getpeername (csock , (struct sockaddr * )& daddr .ip_addr , & daddr_len );
592- }
590+ if (isock == Tsock ) {
591+ #if defined(linux )
592+ /* On Linux && nftabeles/iptables */
593+ memset (& daddr .ip_addr , 0 , daddr_len );
594+ daddr .ip_addr .ss_family = caddr .ss_family ;
595+ ret = getsockopt (csock , SOL_IP , SO_ORIGINAL_DST , & daddr .ip_addr , & daddr_len );
596+ #else
597+ /* On *BSD with PF */
598+ ret = nat_lookup (pfd , & caddr , (struct sockaddr_storage * )tres -> ai_addr , & daddr .ip_addr );
599+ #endif
600+ if (ret ) {
601+ printl (LOG_WARN , "Failed to find the real destination IP, trying to get it from the socket" );
602+ getpeername (csock , (struct sockaddr * )& daddr .ip_addr , & daddr_len );
603+ }
593604
594- printl (LOG_INFO , "The client destination address is: [%s]" , inet2str (& daddr .ip_addr , buf ));
605+ printl (LOG_INFO , "The client destination address is: [%s]" , inet2str (& daddr .ip_addr , buf ));
606+ }
595607
596608 /* -- Process the PIDs list: remove exitted clients and execute workload balance functions ------------------ */
597609 c = pids ;
@@ -648,19 +660,28 @@ All parameters are optional:
648660 pid = getpid ();
649661 printl (LOG_VERB , "A new client process started" );
650662
651- if (!s_ini ) {
663+ if (!s_ini && isock == Tsock ) {
652664 /* -- No proxy server found for the destination IP -------------------------------------------------- */
653665 printl (LOG_INFO , "No proxy server is defined for the destination: [%s]" , inet2str (& daddr .ip_addr , buf ));
654666
655- if ((daddr .ip_addr .ss_family == AF_INET && S4_ADDR (daddr .ip_addr ) == S4_ADDR (* tres -> ai_addr )) ||
667+ if ((daddr .ip_addr .ss_family == AF_INET &&
668+ S4_ADDR (daddr .ip_addr ) == S4_ADDR (* tres -> ai_addr ) &&
669+ SIN4_PORT (daddr .ip_addr ) == SIN4_PORT (* tres -> ai_addr )) ||
656670 (daddr .ip_addr .ss_family == AF_INET6 &&
657- !memcmp (S6_ADDR (daddr .ip_addr ), S6_ADDR (* tres -> ai_addr ), sizeof (S6_ADDR (daddr .ip_addr )))) ||
658- (daddr .ip_addr .ss_family == AF_INET && S4_ADDR (daddr .ip_addr ) == S4_ADDR (* sres -> ai_addr )) ||
671+ !memcmp (S6_ADDR (daddr .ip_addr ), S6_ADDR (* tres -> ai_addr ), sizeof (S6_ADDR (daddr .ip_addr ))) &&
672+ SIN6_PORT (daddr .ip_addr ) == SIN6_PORT (* tres -> ai_addr )) ||
673+ (daddr .ip_addr .ss_family == AF_INET &&
674+ S4_ADDR (daddr .ip_addr ) == S4_ADDR (* sres -> ai_addr ) &&
675+ SIN4_PORT (daddr .ip_addr ) == SIN4_PORT (* sres -> ai_addr )) ||
659676 (daddr .ip_addr .ss_family == AF_INET6 &&
660- !memcmp (S6_ADDR (daddr .ip_addr ), S6_ADDR (* sres -> ai_addr ), sizeof (S6_ADDR (daddr .ip_addr )))) ||
661- (daddr .ip_addr .ss_family == AF_INET && S4_ADDR (daddr .ip_addr ) == S4_ADDR (* hres -> ai_addr )) ||
677+ !memcmp (S6_ADDR (daddr .ip_addr ), S6_ADDR (* sres -> ai_addr ), sizeof (S6_ADDR (daddr .ip_addr ))) &&
678+ SIN6_PORT (daddr .ip_addr ) == SIN6_PORT (* sres -> ai_addr )) ||
679+ (daddr .ip_addr .ss_family == AF_INET &&
680+ S4_ADDR (daddr .ip_addr ) == S4_ADDR (* hres -> ai_addr ) &&
681+ SIN4_PORT (daddr .ip_addr ) == SIN4_PORT (* hres -> ai_addr )) ||
662682 (daddr .ip_addr .ss_family == AF_INET6 &&
663- !memcmp (S6_ADDR (daddr .ip_addr ), S6_ADDR (* hres -> ai_addr ), sizeof (S6_ADDR (daddr .ip_addr ))))) {
683+ !memcmp (S6_ADDR (daddr .ip_addr ), S6_ADDR (* hres -> ai_addr ), sizeof (S6_ADDR (daddr .ip_addr ))) &&
684+ SIN6_PORT (daddr .ip_addr ) == SIN6_PORT (* hres -> ai_addr ))) {
664685 /* Desination address:port is the same as ts-warp incominig (Taransparent, Socks or HTTP) ip:port,
665686 i.e., a client contacted ts-warp dirctly: no NAT/redirection and TS-Warp is not defined as
666687 proxy server */
@@ -935,7 +956,8 @@ All parameters are optional:
935956 inet2str (& sc -> next -> chain_member -> proxy_server , buf ));
936957
937958 if (http_client_request (ssock , & sc -> next -> chain_member -> proxy_server ,
938- sc -> next -> chain_member -> proxy_user , sc -> next -> chain_member -> proxy_password )) {
959+ sc -> next -> chain_member -> proxy_user ,
960+ sc -> next -> chain_member -> proxy_password , sdpi )) {
939961
940962 printl (LOG_WARN , "CHAIN HTTP server returned an error" );
941963 close (csock );
@@ -948,7 +970,7 @@ All parameters are optional:
948970 inet2str (& s_ini -> proxy_server , buf ));
949971
950972 if (http_client_request (ssock ,
951- & s_ini -> proxy_server , s_ini -> proxy_user , s_ini -> proxy_password )) {
973+ & s_ini -> proxy_server , s_ini -> proxy_user , s_ini -> proxy_password , sdpi )) {
952974
953975 printl (LOG_WARN , "CHAIN HTTP server returned an error" );
954976 close (csock );
@@ -1117,7 +1139,7 @@ All parameters are optional:
11171139 printl (LOG_VERB , "Initiate HTTP protocol: request: [%s] -> [%s]" ,
11181140 inet2str (& s_ini -> proxy_server , suf ), inet2str (& daddr .ip_addr , buf ));
11191141
1120- if (http_client_request (ssock , & daddr .ip_addr , s_ini -> proxy_user , s_ini -> proxy_password )) {
1142+ if (http_client_request (ssock , & daddr .ip_addr , s_ini -> proxy_user , s_ini -> proxy_password , sdpi )) {
11211143 printl (LOG_WARN , "HTTP proxy server returned an error" );
11221144 close (csock );
11231145 exit (2 );
@@ -1276,11 +1298,27 @@ All parameters are optional:
12761298 printl (LOG_CRIT , "Error receving data from the client" );
12771299 break ;
12781300 }
1279- while ((snd = send (ssock .s , buf , rec , 0 )) == 0 ) {
1280- printl (LOG_CRIT , "C:[0] -> S:[0] bytes" );
1281- usleep (100 ); /* 0.1 ms */
1282- break ;
1283- }
1301+
1302+ if (sdpi && rec > 1 ) {
1303+ printl (LOG_VERB , "Trying to bypass Deep Packet Inspections" );
1304+
1305+ if ((snd = send (ssock .s , buf , 1 , 0 )) == -1 ) {
1306+ printl (LOG_CRIT , "Error sending data to proxy server" );
1307+ break ;
1308+ }
1309+ int _snd = send (ssock .s , buf + 1 , rec - 1 , 0 );
1310+ if (_snd == -1 ) {
1311+ printl (LOG_CRIT , "Error sending data to proxy server" );
1312+ break ;
1313+ }
1314+ snd += _snd ;
1315+ sdpi = 0 ; /* No need to split more packets */
1316+ } else
1317+ while ((snd = send (ssock .s , buf , rec , 0 )) == 0 ) {
1318+ printl (LOG_CRIT , "C:[0] -> S:[0] bytes" );
1319+ usleep (100 ); /* 0.1 ms */
1320+ break ;
1321+ }
12841322 if (snd == -1 ) {
12851323 printl (LOG_CRIT , "Error sending data to proxy server" );
12861324 break ;
@@ -1420,7 +1458,7 @@ void trap_signal(int sig) {
14201458/* ------------------------------------------------------------------------------------------------------------------ */
14211459void usage (int ecode ) {
14221460 printf ("Usage:\n\
1423- ts-warp -T IP:Port -S IP:Port -H IP:Port -c file.ini -l file.log -v 0-4 -t file.act -d -p file.pid -f -u user -h\n\n\
1461+ ts-warp -T IP:Port -S IP:Port -H IP:Port -c file.ini -l file.log -v 0-4 -t file.act -d -p file.pid -f -u user -D - h\n\n\
14241462Version:\n\
14251463 %s-%s\n\n\
14261464All parameters are optional:\n\
@@ -1438,6 +1476,7 @@ All parameters are optional:\n\
14381476 -f\t\t Force start\n\
14391477 \n\
14401478 -u user\t A user to run ts-warp, default: %s. Note, this option has no effect on macOS\n\
1479+ -D\t\t Do not try bypass Deep Packet Inspections\n\
14411480 \n\
14421481 -h\t\t This message\n\n" ,
14431482 PROG_NAME , PROG_VERSION , INI_FILE_NAME , LOG_FILE_NAME , LOG_LEVEL_DEFAULT , PID_FILE_NAME , RUNAS_USER );
0 commit comments