Skip to content

Commit 1eb5cfa

Browse files
feat: Implement IPv6 support
1 parent 37d614f commit 1eb5cfa

File tree

14 files changed

+456
-73
lines changed

14 files changed

+456
-73
lines changed

include/globvar.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525

2626
struct fh_context {
2727
int exit;
28-
int sockfd;
28+
int sock4fd;
29+
int sock6fd;
2930
FILE *logfp;
3031

3132
/* -d */ int daemon;

include/ipv6ipt.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@
2020
#ifndef FH_IPV6IPT_H
2121
#define FH_IPV6IPT_H
2222

23-
/* TODO: NOT IMPLEMENTED */
2423
int fh_ipt6_flush(int auto_create);
2524

26-
/* TODO: NOT IMPLEMENTED */
2725
int fh_ipt6_add(void);
2826

2927
#endif /* FH_IPV6IPT_H */

include/ipv6nft.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@
2020
#ifndef FH_IPV6NFT_H
2121
#define FH_IPV6NFT_H
2222

23-
/* TODO: NOT IMPLEMENTED */
2423
int fh_nft6_flush(int auto_create);
2524

26-
/* TODO: NOT IMPLEMENTED */
2725
int fh_nft6_add(void);
2826

2927
#endif /* FH_IPV6NFT_H */

include/ipv6pkt.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,10 @@
2424
#include <stdlib.h>
2525
#include <netinet/tcp.h>
2626

27-
/* TODO: NOT IMPLEMENTED */
2827
int fh_pkt6_parse(void *pkt_data, int pkt_len, struct sockaddr *saddr,
2928
struct sockaddr *daddr, struct tcphdr **tcph_ptr,
3029
int *tcp_payload_len);
3130

32-
/* TODO: NOT IMPLEMENTED */
3331
int fh_pkt6_make(char *buffer, size_t buffer_size, struct sockaddr *saddr,
3432
struct sockaddr *daddr, uint16_t sport_be, uint16_t dport_be,
3533
uint32_t seq_be, uint32_t ackseq_be, int psh,

include/rawsock.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#ifndef FH_RAWSOCK_H
2121
#define FH_RAWSOCK_H
2222

23-
int fh_rawsock_setup(void);
23+
int fh_rawsock_setup(int af);
2424

2525
void fh_rawsock_cleanup(void);
2626

src/globvar.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
#include <stdio.h>
2525

2626
struct fh_context g_ctx = {.exit = 0,
27-
.sockfd = -1,
27+
.sock4fd = -1,
28+
.sock6fd = -1,
2829
.logfp = NULL,
2930

3031
/* -d */ .daemon = 0,

src/ipv4nft.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
int fh_nft4_flush(int auto_create)
3131
{
3232
int res;
33-
char *nft_flush_cmd[] = {"nft", "flush table fakehttp", NULL};
33+
char *nft_flush_cmd[] = {"nft", "flush table ip fakehttp", NULL};
3434
char *nft_cmd[] = {"nft", "-f", "-", NULL};
3535
char *nft_create_conf =
3636
"table ip fakehttp {\n"

src/ipv6ipt.c

Lines changed: 127 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,139 @@
2727
#include "logging.h"
2828
#include "process.h"
2929

30-
/* TODO: NOT IMPLEMENTED */
3130
int fh_ipt6_flush(int auto_create)
3231
{
33-
(void) auto_create;
32+
int res;
33+
size_t i, cnt;
34+
char *ipt_flush_cmd[] = {"ip6tables", "-w", "-t", "mangle",
35+
"-F", "FAKEHTTP", NULL};
36+
char *ipt_create_cmds[][32] = {
37+
{"ip6tables", "-w", "-t", "mangle", "-N", "FAKEHTTP", NULL},
3438

35-
return -1;
39+
{"ip6tables", "-w", "-t", "mangle", "-I", "INPUT", "-j", "FAKEHTTP",
40+
NULL},
41+
42+
{"ip6tables", "-w", "-t", "mangle", "-I", "FORWARD", "-j", "FAKEHTTP",
43+
NULL}};
44+
45+
res = fh_execute_command(ipt_flush_cmd, 1, NULL);
46+
if (res < 0) {
47+
if (!auto_create) {
48+
E(T(fh_execute_command));
49+
return -1;
50+
}
51+
52+
cnt = sizeof(ipt_create_cmds) / sizeof(*ipt_create_cmds);
53+
for (i = 0; i < cnt; i++) {
54+
res = fh_execute_command(ipt_create_cmds[i], 0, NULL);
55+
if (res < 0) {
56+
E(T(fh_execute_command));
57+
return -1;
58+
}
59+
}
60+
}
61+
62+
return 0;
3663
}
3764

3865

39-
/* TODO: NOT IMPLEMENTED */
4066
int fh_ipt6_add(void)
4167
{
42-
return -1;
68+
char xmark_str[64], nfqnum_str[32], iface_str[32];
69+
size_t i, ipt_cmds_cnt, ipt_opt_cmds_cnt;
70+
int res;
71+
char *ipt_cmds[][32] = {
72+
/*
73+
exclude marked packets
74+
*/
75+
{"ip6tables", "-w", "-t", "mangle", "-A", "FAKEHTTP", "-m", "mark",
76+
"--mark", xmark_str, "-j", "CONNMARK", "--set-xmark", xmark_str,
77+
NULL},
78+
79+
{"ip6tables", "-w", "-t", "mangle", "-A", "FAKEHTTP", "-m", "connmark",
80+
"--mark", xmark_str, "-j", "MARK", "--set-xmark", xmark_str, NULL},
81+
82+
{"ip6tables", "-w", "-t", "mangle", "-A", "FAKEHTTP", "-m", "mark",
83+
"--mark", xmark_str, "-j", "RETURN", NULL},
84+
85+
/*
86+
exclude special IPv6 addresses
87+
*/
88+
{"ip6tables", "-w", "-t", "mangle", "-A", "FAKEHTTP", "-s", "::/127",
89+
"-j", "RETURN", NULL},
90+
91+
{"ip6tables", "-w", "-t", "mangle", "-A", "FAKEHTTP", "-s",
92+
"::ffff:0:0/96", "-j", "RETURN", NULL},
93+
94+
{"ip6tables", "-w", "-t", "mangle", "-A", "FAKEHTTP", "-s",
95+
"64:ff9b::/96", "-j", "RETURN", NULL},
96+
97+
{"ip6tables", "-w", "-t", "mangle", "-A", "FAKEHTTP", "-s",
98+
"64:ff9b:1::/48", "-j", "RETURN", NULL},
99+
100+
{"ip6tables", "-w", "-t", "mangle", "-A", "FAKEHTTP", "-s",
101+
"2002::/16", "-j", "RETURN", NULL},
102+
103+
{"ip6tables", "-w", "-t", "mangle", "-A", "FAKEHTTP", "-s", "fc00::/7",
104+
"-j", "RETURN", NULL},
105+
106+
{"ip6tables", "-w", "-t", "mangle", "-A", "FAKEHTTP", "-s",
107+
"fe80::/10", "-j", "RETURN", NULL},
108+
109+
/*
110+
send to nfqueue
111+
*/
112+
{"ip6tables", "-w", "-t", "mangle", "-A", "FAKEHTTP", "-i", iface_str,
113+
"-p", "tcp", "--tcp-flags", "ACK,FIN,RST", "ACK", "-j", "NFQUEUE",
114+
"--queue-bypass", "--queue-num", nfqnum_str, NULL}};
115+
116+
char *ipt_opt_cmds[][32] = {
117+
/*
118+
exclude packets from connections with more than 32 packets
119+
*/
120+
{"ip6tables", "-w", "-t", "mangle", "-I", "FAKEHTTP", "-m",
121+
"connbytes", "!", "--connbytes", "0:32", "--connbytes-dir", "both",
122+
"--connbytes-mode", "packets", "-j", "RETURN", NULL},
123+
124+
/*
125+
exclude big packets
126+
*/
127+
{"ip6tables", "-w", "-t", "mangle", "-I", "FAKEHTTP", "-m", "length",
128+
"!", "--length", "0:120", "-j", "RETURN", NULL}};
129+
130+
ipt_cmds_cnt = sizeof(ipt_cmds) / sizeof(*ipt_cmds);
131+
ipt_opt_cmds_cnt = sizeof(ipt_opt_cmds) / sizeof(*ipt_opt_cmds);
132+
133+
res = snprintf(xmark_str, sizeof(xmark_str), "%" PRIu32 "/%" PRIu32,
134+
g_ctx.fwmark, g_ctx.fwmask);
135+
if (res < 0 || (size_t) res >= sizeof(xmark_str)) {
136+
E("ERROR: snprintf(): %s", "failure");
137+
return -1;
138+
}
139+
140+
res = snprintf(nfqnum_str, sizeof(nfqnum_str), "%" PRIu32, g_ctx.nfqnum);
141+
if (res < 0 || (size_t) res >= sizeof(nfqnum_str)) {
142+
E("ERROR: snprintf(): %s", "failure");
143+
return -1;
144+
}
145+
146+
res = snprintf(iface_str, sizeof(iface_str), "%s", g_ctx.iface);
147+
if (res < 0 || (size_t) res >= sizeof(iface_str)) {
148+
E("ERROR: snprintf(): %s", "failure");
149+
return -1;
150+
}
151+
152+
for (i = 0; i < ipt_cmds_cnt; i++) {
153+
res = fh_execute_command(ipt_cmds[i], 0, NULL);
154+
if (res < 0) {
155+
E(T(fh_execute_command));
156+
return -1;
157+
}
158+
}
159+
160+
for (i = 0; i < ipt_opt_cmds_cnt; i++) {
161+
fh_execute_command(ipt_opt_cmds[i], 1, NULL);
162+
}
163+
164+
return 0;
43165
}

src/ipv6nft.c

Lines changed: 115 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,127 @@
2727
#include "logging.h"
2828
#include "process.h"
2929

30-
/* TODO: NOT IMPLEMENTED */
3130
int fh_nft6_flush(int auto_create)
3231
{
33-
(void) auto_create;
32+
int res;
33+
char *nft_flush_cmd[] = {"nft", "flush table ip6 fakehttp", NULL};
34+
char *nft_cmd[] = {"nft", "-f", "-", NULL};
35+
char *nft_create_conf =
36+
"table ip6 fakehttp {\n"
37+
" chain fh_input {\n"
38+
" type filter hook input priority mangle - 5;\n"
39+
" policy accept;\n"
40+
" }\n"
41+
"\n"
42+
" chain fh_output {\n"
43+
" type filter hook forward priority mangle - 5;\n"
44+
" policy accept;\n"
45+
" }\n"
46+
"\n"
47+
" chain fh_rules {\n"
48+
" }\n"
49+
"}\n";
3450

35-
return -1;
51+
res = fh_execute_command(nft_flush_cmd, 1, NULL);
52+
if (res < 0) {
53+
if (!auto_create) {
54+
E(T(fh_execute_command));
55+
return -1;
56+
}
57+
58+
res = fh_execute_command(nft_cmd, 0, nft_create_conf);
59+
if (res < 0) {
60+
E(T(fh_execute_command));
61+
return -1;
62+
}
63+
}
64+
65+
return 0;
3666
}
3767

3868

39-
/* TODO: NOT IMPLEMENTED */
4069
int fh_nft6_add(void)
4170
{
42-
return -1;
71+
size_t i, nft_opt_cmds_cnt;
72+
int res;
73+
char *nft_cmd[] = {"nft", "-f", "-", NULL};
74+
char nft_conf_buff[2048];
75+
char *nft_conf_fmt =
76+
"table ip6 fakehttp {\n"
77+
" chain fh_input {\n"
78+
" jump fh_rules;\n"
79+
" }\n"
80+
"\n"
81+
" chain fh_output {\n"
82+
" jump fh_rules;\n"
83+
" }\n"
84+
"\n"
85+
" chain fh_rules {\n"
86+
87+
/*
88+
exclude marked packets
89+
*/
90+
" meta mark and %" PRIu32 " == %" PRIu32
91+
" ct mark set ct mark and %" PRIu32 " xor %" PRIu32 ";\n"
92+
93+
" ct mark and %" PRIu32 " == %" PRIu32
94+
" meta mark set mark and %" PRIu32 " xor %" PRIu32 ";\n"
95+
96+
" meta mark and %" PRIu32 " == %" PRIu32 " return;\n"
97+
98+
/*
99+
exclude special IPv6 addresses
100+
*/
101+
" ip6 saddr ::/127 return;\n"
102+
" ip6 saddr ::ffff:0:0/96 return;\n"
103+
" ip6 saddr 64:ff9b::/96 return;\n"
104+
" ip6 saddr 64:ff9b:1::/48 return;\n"
105+
" ip6 saddr 2002::/16 return;\n"
106+
" ip6 saddr fc00::/7 return;\n"
107+
" ip6 saddr fe80::/10 return;\n"
108+
109+
/*
110+
send to nfqueue
111+
*/
112+
" iifname \"%s\" tcp flags & (fin | rst | ack) == ack queue "
113+
"num %" PRIu32 " bypass;\n"
114+
115+
" }\n"
116+
"}\n";
117+
118+
char *nft_opt_cmds[][32] = {
119+
/*
120+
exclude packets from connections with more than 32 packets
121+
*/
122+
{"nft", "insert rule ip6 fakehttp fh_rules ct packets > 32 return",
123+
NULL},
124+
125+
/*
126+
exclude big packets
127+
*/
128+
{"nft", "insert rule ip6 fakehttp fh_rules meta length > 120 return",
129+
NULL}};
130+
131+
nft_opt_cmds_cnt = sizeof(nft_opt_cmds) / sizeof(*nft_opt_cmds);
132+
133+
res = snprintf(nft_conf_buff, sizeof(nft_conf_buff), nft_conf_fmt,
134+
g_ctx.fwmask, g_ctx.fwmark, ~g_ctx.fwmask, g_ctx.fwmark,
135+
g_ctx.fwmask, g_ctx.fwmark, ~g_ctx.fwmask, g_ctx.fwmark,
136+
g_ctx.fwmask, g_ctx.fwmark, g_ctx.iface, g_ctx.nfqnum);
137+
if (res < 0 || (size_t) res >= sizeof(nft_conf_buff)) {
138+
E("ERROR: snprintf(): %s", "failure");
139+
return -1;
140+
}
141+
142+
res = fh_execute_command(nft_cmd, 1, nft_conf_buff);
143+
if (res < 0) {
144+
E(T(fh_execute_command));
145+
return -1;
146+
}
147+
148+
for (i = 0; i < nft_opt_cmds_cnt; i++) {
149+
fh_execute_command(nft_opt_cmds[i], 1, NULL);
150+
}
151+
152+
return 0;
43153
}

0 commit comments

Comments
 (0)