@@ -249,14 +249,28 @@ static int kill_running(int signal)
249249}
250250
251251
252- static int execute_command (char * * argv , int silent )
252+ static int execute_command (char * * argv , int silent , char * input )
253253{
254- int res , status , fd , i ;
254+ int res , pipefd [2 ], status , fd , i ;
255+ size_t input_len , written ;
256+ ssize_t n ;
255257 pid_t pid ;
256258
259+ if (input ) {
260+ res = pipe (pipefd );
261+ if (res < 0 ) {
262+ E ("ERROR: pipe(): %s" , strerror (errno ));
263+ return -1 ;
264+ }
265+ }
266+
257267 pid = fork ();
258268 if (pid < 0 ) {
259269 E ("ERROR: fork(): %s" , strerror (errno ));
270+ if (input ) {
271+ close (pipefd [0 ]);
272+ close (pipefd [1 ]);
273+ }
260274 return -1 ;
261275 }
262276
@@ -291,13 +305,36 @@ static int execute_command(char **argv, int silent)
291305 close (fd );
292306 }
293307
308+ if (input ) {
309+ close (pipefd [1 ]);
310+ res = dup2 (pipefd [0 ], STDIN_FILENO );
311+ if (res < 0 ) {
312+ E ("ERROR: dup2(): %s" , strerror (errno ));
313+ _exit (EXIT_FAILURE );
314+ }
315+ close (pipefd [0 ]);
316+ }
317+
294318 execvp (argv [0 ], argv );
295319
296320 E ("ERROR: execvp(): %s: %s" , argv [0 ], strerror (errno ));
297321
298322 _exit (EXIT_FAILURE );
299323 }
300324
325+ if (input ) {
326+ close (pipefd [0 ]);
327+ input_len = strlen (input );
328+ for (written = 0 ; written < input_len ; written += n ) {
329+ n = write (pipefd [1 ], input + written , input_len - written );
330+ if (n < 0 ) {
331+ E ("ERROR: write(): %s" , strerror (errno ));
332+ break ;
333+ }
334+ }
335+ close (pipefd [1 ]);
336+ }
337+
301338 if (waitpid (pid , & status , 0 ) < 0 ) {
302339 E ("ERROR: waitpid(): %s" , strerror (errno ));
303340 goto child_failed ;
@@ -324,36 +361,41 @@ static int nft_is_working(void)
324361{
325362 char * nft_ver_cmd [] = {"nft" , "--version" , NULL };
326363
327- return !execute_command (nft_ver_cmd , 1 );
364+ return !execute_command (nft_ver_cmd , 1 , NULL );
328365}
329366
330367
331368static int nft_rules_flush (int auto_create )
332369{
333370 int res ;
334- size_t i , cnt ;
335- char * nft_argv [] = {"nft" , NULL , NULL };
336- char * nft_flush_cmd = "flush chain ip mangle FAKEHTTP" ;
337- char * nft_create_cmds [] = {"add chain ip mangle FAKEHTTP" ,
338- "flush chain ip mangle FAKEHTTP" ,
339- "insert rule ip mangle INPUT jump FAKEHTTP" ,
340- "insert rule ip mangle FORWARD jump FAKEHTTP" };
341-
342- nft_argv [1 ] = nft_flush_cmd ;
343- res = execute_command (nft_argv , 1 );
371+ char * nft_flush_cmd [] = {"nft" , "flush table fakehttp" , NULL };
372+ char * nft_cmd [] = {"nft" , "-f" , "-" , NULL };
373+ char * nft_create_conf =
374+ "table ip fakehttp {\n"
375+ " chain fh_input {\n"
376+ " type filter hook input priority mangle - 5;\n"
377+ " policy accept;\n"
378+ " }\n"
379+ "\n"
380+ " chain fh_output {\n"
381+ " type filter hook forward priority mangle - 5;\n"
382+ " policy accept;\n"
383+ " }\n"
384+ "\n"
385+ " chain fh_rules {\n"
386+ " }\n"
387+ "}\n" ;
388+
389+ res = execute_command (nft_flush_cmd , 1 , NULL );
344390 if (res < 0 ) {
345391 if (!auto_create ) {
346392 return -1 ;
347393 }
348394
349- cnt = sizeof (nft_create_cmds ) / sizeof (* nft_create_cmds );
350- for (i = 0 ; i < cnt ; i ++ ) {
351- nft_argv [1 ] = nft_create_cmds [i ];
352- res = execute_command (nft_argv , 0 );
353- if (res ) {
354- E ("ERROR: execute_command()" );
355- return -1 ;
356- }
395+ res = execute_command (nft_cmd , 0 , nft_create_conf );
396+ if (res ) {
397+ E ("ERROR: execute_command()" );
398+ return -1 ;
357399 }
358400 }
359401
@@ -363,96 +405,82 @@ static int nft_rules_flush(int auto_create)
363405
364406static int nft_rules_setup (void )
365407{
366- char mark_cmd_01 [256 ], mark_cmd_02 [256 ], mark_cmd_03 [256 ];
367- char queue_cmd_01 [256 ], * fmt ;
368- size_t i , nft_cmds_cnt , nft_opt_cmds_cnt ;
408+ size_t i , nft_opt_cmds_cnt ;
369409 int res ;
410+ char * nft_cmd [] = {"nft" , "-f" , "-" , NULL };
411+ char nft_conf_buff [2048 ];
412+ char * nft_conf_fmt =
413+ "table ip fakehttp {\n"
414+ " chain fh_input {\n"
415+ " jump fh_rules;\n"
416+ " }\n"
417+ "\n"
418+ " chain fh_output {\n"
419+ " jump fh_rules;\n"
420+ " }\n"
421+ "\n"
422+ " chain fh_rules {\n"
370423
371- char * nft_argv [] = {"nft" , NULL , NULL };
372- char * nft_cmds [] = {
373424 /*
374425 exclude marked packets
375426 */
376- mark_cmd_01 , mark_cmd_02 , mark_cmd_03 ,
427+ " meta mark and %" PRIu32 " == %" PRIu32
428+ " ct mark set ct mark and %" PRIu32 " xor %" PRIu32 ";\n"
429+ " ct mark and %" PRIu32 " == %" PRIu32
430+ " meta mark set mark and %" PRIu32 " xor %" PRIu32 ";\n"
431+ " meta mark and %" PRIu32 " == %" PRIu32 " return;\n"
377432
378433 /*
379434 exclude local IPs
380435 */
381- "add rule ip mangle FAKEHTTP ip saddr 0.0.0.0/8 return" ,
382- "add rule ip mangle FAKEHTTP ip saddr 10.0.0.0/8 return" ,
383- "add rule ip mangle FAKEHTTP ip saddr 100.64.0.0/10 return" ,
384- "add rule ip mangle FAKEHTTP ip saddr 127.0.0.0/8 return" ,
385- "add rule ip mangle FAKEHTTP ip saddr 169.254.0.0/16 return" ,
386- "add rule ip mangle FAKEHTTP ip saddr 172.16.0.0/12 return" ,
387- "add rule ip mangle FAKEHTTP ip saddr 192.168.0.0/16 return" ,
388- "add rule ip mangle FAKEHTTP ip saddr 224.0.0.0/3 return" ,
436+ " ip saddr 0.0.0.0/8 return;\n"
437+ " ip saddr 10.0.0.0/8 return;\n"
438+ " ip saddr 100.64.0.0/10 return;\n"
439+ " ip saddr 127.0.0.0/8 return;\n"
440+ " ip saddr 169.254.0.0/16 return;\n"
441+ " ip saddr 172.16.0.0/12 return;\n"
442+ " ip saddr 192.168.0.0/16 return;\n"
443+ " ip saddr 224.0.0.0/3 return;\n"
389444
390445 /*
391446 send to nfqueue
392447 */
393- queue_cmd_01 };
448+ " iifname \"%s\" tcp flags & (fin | rst | ack) == ack queue "
449+ "num %" PRIu32 " bypass;\n"
450+ " }\n"
451+ "}\n" ;
394452
395- char * nft_opt_cmds [] = {
453+ char * nft_opt_cmds [][ 32 ] = {
396454 /*
397455 exclude packets from connections with more than 32 packets
398456 */
399- "insert rule ip mangle FAKEHTTP ct packets > 32 return" ,
457+ {"nft" , "insert rule ip fakehttp fh_rules ct packets > 32 return" ,
458+ NULL },
400459
401460 /*
402461 exclude big packets
403462 */
404- "insert rule ip mangle FAKEHTTP meta length > 120 return" };
463+ {"nft" , "insert rule ip fakehttp fh_rules meta length > 120 return" ,
464+ NULL }};
405465
406- nft_cmds_cnt = sizeof (nft_cmds ) / sizeof (* nft_cmds );
407466 nft_opt_cmds_cnt = sizeof (nft_opt_cmds ) / sizeof (* nft_opt_cmds );
408467
409- fmt = "add rule ip mangle FAKEHTTP meta mark and %" PRIu32 " == %" PRIu32
410- " ct mark set ct mark and %" PRIu32 " xor %" PRIu32 ;
411- res = snprintf (mark_cmd_01 , sizeof (mark_cmd_01 ), fmt , g_fwmask , g_fwmark ,
412- ~g_fwmask , g_fwmark );
413- if (res < 0 || (size_t ) res >= sizeof (mark_cmd_01 )) {
414- E ("ERROR: snprintf()" );
415- return -1 ;
416- }
417-
418- fmt = "add rule ip mangle FAKEHTTP ct mark and %" PRIu32 " == %" PRIu32
419- " meta mark set mark and %" PRIu32 " xor %" PRIu32 ;
420- res = snprintf (mark_cmd_02 , sizeof (mark_cmd_02 ), fmt , g_fwmask , g_fwmark ,
421- ~g_fwmask , g_fwmark );
422- if (res < 0 || (size_t ) res >= sizeof (mark_cmd_02 )) {
423- E ("ERROR: snprintf()" );
424- return -1 ;
425- }
426-
427-
428- fmt = "add rule ip mangle FAKEHTTP meta mark and %" PRIu32 " == %" PRIu32
429- " return" ;
430- res = snprintf (mark_cmd_03 , sizeof (mark_cmd_03 ), fmt , g_fwmask , g_fwmark );
431- if (res < 0 || (size_t ) res >= sizeof (mark_cmd_03 )) {
468+ res = snprintf (nft_conf_buff , sizeof (nft_conf_buff ), nft_conf_fmt ,
469+ g_fwmask , g_fwmark , ~g_fwmask , g_fwmark , g_fwmask , g_fwmark ,
470+ ~g_fwmask , g_fwmark , g_fwmask , g_fwmark , g_iface , g_nfqnum );
471+ if (res < 0 || (size_t ) res >= sizeof (nft_conf_buff )) {
432472 E ("ERROR: snprintf()" );
433473 return -1 ;
434474 }
435475
436- fmt = "add rule ip mangle FAKEHTTP iifname \"%s\" tcp flags & (fin | rst "
437- "| ack) == ack queue num %" PRIu32 " bypass" ;
438- res = snprintf (queue_cmd_01 , sizeof (queue_cmd_01 ), fmt , g_iface , g_nfqnum );
439- if (res < 0 || (size_t ) res >= sizeof (queue_cmd_01 )) {
440- E ("ERROR: snprintf()" );
476+ res = execute_command (nft_cmd , 1 , nft_conf_buff );
477+ if (res ) {
478+ E ("ERROR: execute_command()" );
441479 return -1 ;
442480 }
443481
444- for (i = 0 ; i < nft_cmds_cnt ; i ++ ) {
445- nft_argv [1 ] = nft_cmds [i ];
446- res = execute_command (nft_argv , 0 );
447- if (res ) {
448- E ("ERROR: execute_command()" );
449- return -1 ;
450- }
451- }
452-
453482 for (i = 0 ; i < nft_opt_cmds_cnt ; i ++ ) {
454- nft_argv [1 ] = nft_opt_cmds [i ];
455- execute_command (nft_argv , 1 );
483+ execute_command (nft_opt_cmds [i ], 1 , NULL );
456484 }
457485
458486 return 0 ;
@@ -474,15 +502,15 @@ static int ipt_rules_flush(int auto_create)
474502 {"iptables" , "-w" , "-t" , "mangle" , "-I" , "FORWARD" , "-j" , "FAKEHTTP" ,
475503 NULL }};
476504
477- res = execute_command (ipt_flush_cmd , 1 );
505+ res = execute_command (ipt_flush_cmd , 1 , NULL );
478506 if (res < 0 ) {
479507 if (!auto_create ) {
480508 return -1 ;
481509 }
482510
483511 cnt = sizeof (ipt_create_cmds ) / sizeof (* ipt_create_cmds );
484512 for (i = 0 ; i < cnt ; i ++ ) {
485- res = execute_command (ipt_create_cmds [i ], 0 );
513+ res = execute_command (ipt_create_cmds [i ], 0 , NULL );
486514 if (res ) {
487515 E ("ERROR: execute_command()" );
488516 return -1 ;
@@ -584,15 +612,15 @@ static int ipt_rules_setup(void)
584612 }
585613
586614 for (i = 0 ; i < ipt_cmds_cnt ; i ++ ) {
587- res = execute_command (ipt_cmds [i ], 0 );
615+ res = execute_command (ipt_cmds [i ], 0 , NULL );
588616 if (res ) {
589617 E ("ERROR: execute_command()" );
590618 return -1 ;
591619 }
592620 }
593621
594622 for (i = 0 ; i < ipt_opt_cmds_cnt ; i ++ ) {
595- execute_command (ipt_opt_cmds [i ], 1 );
623+ execute_command (ipt_opt_cmds [i ], 1 , NULL );
596624 }
597625
598626 return 0 ;
0 commit comments