Skip to content

Commit d9bf016

Browse files
fix: Rewrite nft commands
1 parent 02b4f50 commit d9bf016

1 file changed

Lines changed: 111 additions & 83 deletions

File tree

src/fakehttp.c

Lines changed: 111 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -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

331368
static 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

364406
static 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

Comments
 (0)