Skip to content

Commit 2cf2573

Browse files
feat: Use AF_PACKET raw socket instead of AF_INET/AF_INET6
1 parent 22b1736 commit 2cf2573

10 files changed

Lines changed: 69 additions & 105 deletions

File tree

include/globvar.h

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

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

3231
/* -d */ int daemon;

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(int af);
23+
int fh_rawsock_setup(void);
2424

2525
void fh_rawsock_cleanup(void);
2626

src/globvar.c

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

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

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

src/ipv4ipt.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,8 @@ int fh_ipt4_setup(void)
3535
char *ipt_cmds[][32] = {
3636
{"iptables", "-w", "-t", "mangle", "-N", "FAKEHTTP", NULL},
3737

38-
{"iptables", "-w", "-t", "mangle", "-I", "INPUT", "-j", "FAKEHTTP",
39-
NULL},
40-
41-
{"iptables", "-w", "-t", "mangle", "-I", "FORWARD", "-j", "FAKEHTTP",
42-
NULL},
38+
{"iptables", "-w", "-t", "mangle", "-I", "PREROUTING", "-j",
39+
"FAKEHTTP", NULL},
4340

4441
/*
4542
exclude marked packets

src/ipv4nft.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,8 @@ int fh_nft4_setup(void)
3535
char nft_conf_buff[2048];
3636
char *nft_conf_fmt =
3737
"table ip fakehttp {\n"
38-
" chain fh_input {\n"
39-
" type filter hook input priority mangle - 5;\n"
40-
" policy accept;\n"
41-
" jump fh_rules;\n"
42-
" }\n"
43-
"\n"
44-
" chain fh_forward {\n"
45-
" type filter hook forward priority mangle - 5;\n"
38+
" chain fh_prerouting {\n"
39+
" type filter hook prerouting priority mangle - 5;\n"
4640
" policy accept;\n"
4741
" jump fh_rules;\n"
4842
" }\n"

src/ipv6ipt.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,8 @@ int fh_ipt6_setup(void)
3535
char *ipt_cmds[][32] = {
3636
{"ip6tables", "-w", "-t", "mangle", "-N", "FAKEHTTP", NULL},
3737

38-
{"ip6tables", "-w", "-t", "mangle", "-I", "INPUT", "-j", "FAKEHTTP",
39-
NULL},
40-
41-
{"ip6tables", "-w", "-t", "mangle", "-I", "FORWARD", "-j", "FAKEHTTP",
42-
NULL},
38+
{"ip6tables", "-w", "-t", "mangle", "-I", "PREROUTING", "-j",
39+
"FAKEHTTP", NULL},
4340

4441
/*
4542
exclude marked packets

src/ipv6nft.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,8 @@ int fh_nft6_setup(void)
3535
char nft_conf_buff[2048];
3636
char *nft_conf_fmt =
3737
"table ip6 fakehttp {\n"
38-
" chain fh_input {\n"
39-
" type filter hook input priority mangle - 5;\n"
40-
" policy accept;\n"
41-
" jump fh_rules;\n"
42-
" }\n"
43-
"\n"
44-
" chain fh_forward {\n"
45-
" type filter hook forward priority mangle - 5;\n"
38+
" chain fh_prerouting {\n"
39+
" type filter hook prerouting priority mangle - 5;\n"
4640
" policy accept;\n"
4741
" jump fh_rules;\n"
4842
" }\n"

src/mainfun.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -249,13 +249,7 @@ int main(int argc, char *argv[])
249249
E("Home page: https://github.com/MikeWang000000/FakeHTTP");
250250
E("");
251251

252-
res = fh_rawsock_setup(AF_INET);
253-
if (res < 0) {
254-
EE(T(fh_rawsock_setup));
255-
goto cleanup_logger;
256-
}
257-
258-
res = fh_rawsock_setup(AF_INET6);
252+
res = fh_rawsock_setup();
259253
if (res < 0) {
260254
EE(T(fh_rawsock_setup));
261255
goto cleanup_logger;

src/nfqueue.c

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <netinet/ip.h>
3030
#include <netinet/tcp.h>
3131
#include <sys/socket.h>
32+
#include <linux/if_packet.h>
3233
#include <linux/netfilter.h>
3334
#include <linux/netfilter/nfnetlink_queue.h>
3435
#include <libnetfilter_queue/libnetfilter_queue.h>
@@ -71,17 +72,15 @@ static void ipaddr_to_str(struct sockaddr *addr, char ipstr[INET6_ADDRSTRLEN])
7172
}
7273

7374

74-
static int send_ack(struct sockaddr *saddr, struct sockaddr *daddr,
75-
uint16_t sport_be, uint16_t dport_be, uint32_t seq_be,
76-
uint32_t ackseq_be)
75+
static int send_ack(struct sockaddr_ll *sll, struct sockaddr *saddr,
76+
struct sockaddr *daddr, uint16_t sport_be,
77+
uint16_t dport_be, uint32_t seq_be, uint32_t ackseq_be)
7778
{
78-
int pkt_len, addr_len, sock_fd;
79+
int pkt_len;
7980
ssize_t nbytes;
8081
char pkt_buff[1024];
8182

8283
if (daddr->sa_family == AF_INET) {
83-
sock_fd = g_ctx.sock4fd;
84-
addr_len = sizeof(struct sockaddr_in);
8584
pkt_len = fh_pkt4_make(pkt_buff, sizeof(pkt_buff), saddr, daddr,
8685
sport_be, dport_be, seq_be, ackseq_be, 0, NULL,
8786
0);
@@ -90,8 +89,6 @@ static int send_ack(struct sockaddr *saddr, struct sockaddr *daddr,
9089
return -1;
9190
}
9291
} else if (daddr->sa_family == AF_INET6) {
93-
sock_fd = g_ctx.sock6fd;
94-
addr_len = sizeof(struct sockaddr_in6);
9592
pkt_len = fh_pkt6_make(pkt_buff, sizeof(pkt_buff), saddr, daddr,
9693
sport_be, dport_be, seq_be, ackseq_be, 0, NULL,
9794
0);
@@ -104,7 +101,8 @@ static int send_ack(struct sockaddr *saddr, struct sockaddr *daddr,
104101
return -1;
105102
}
106103

107-
nbytes = sendto(sock_fd, pkt_buff, pkt_len, 0, daddr, addr_len);
104+
nbytes = sendto(g_ctx.sockfd, pkt_buff, pkt_len, 0,
105+
(struct sockaddr *) sll, sizeof(*sll));
108106
if (nbytes < 0) {
109107
E("ERROR: sendto(): %s", strerror(errno));
110108
return -1;
@@ -114,16 +112,16 @@ static int send_ack(struct sockaddr *saddr, struct sockaddr *daddr,
114112
}
115113

116114

117-
static int send_http(struct sockaddr *saddr, struct sockaddr *daddr,
118-
uint16_t sport_be, uint16_t dport_be, uint32_t seq_be,
119-
uint32_t ackseq_be)
115+
static int send_http(struct sockaddr_ll *sll, struct sockaddr *saddr,
116+
struct sockaddr *daddr, uint16_t sport_be,
117+
uint16_t dport_be, uint32_t seq_be, uint32_t ackseq_be)
120118
{
121119
static const char *http_fmt = "GET / HTTP/1.1\r\n"
122120
"Host: %s\r\n"
123121
"Accept: */*\r\n"
124122
"\r\n";
125123

126-
int http_len, pkt_len, addr_len, sock_fd;
124+
int http_len, pkt_len;
127125
ssize_t nbytes;
128126
char http_buff[512], pkt_buff[1024];
129127

@@ -135,8 +133,6 @@ static int send_http(struct sockaddr *saddr, struct sockaddr *daddr,
135133
}
136134

137135
if (daddr->sa_family == AF_INET) {
138-
sock_fd = g_ctx.sock4fd;
139-
addr_len = sizeof(struct sockaddr_in);
140136
pkt_len = fh_pkt4_make(pkt_buff, sizeof(pkt_buff), saddr, daddr,
141137
sport_be, dport_be, seq_be, ackseq_be, 1,
142138
http_buff, http_len);
@@ -145,8 +141,6 @@ static int send_http(struct sockaddr *saddr, struct sockaddr *daddr,
145141
return -1;
146142
}
147143
} else if (daddr->sa_family == AF_INET6) {
148-
sock_fd = g_ctx.sock6fd;
149-
addr_len = sizeof(struct sockaddr_in6);
150144
pkt_len = fh_pkt6_make(pkt_buff, sizeof(pkt_buff), saddr, daddr,
151145
sport_be, dport_be, seq_be, ackseq_be, 1,
152146
http_buff, http_len);
@@ -159,7 +153,8 @@ static int send_http(struct sockaddr *saddr, struct sockaddr *daddr,
159153
return -1;
160154
}
161155

162-
nbytes = sendto(sock_fd, pkt_buff, pkt_len, 0, daddr, addr_len);
156+
nbytes = sendto(g_ctx.sockfd, pkt_buff, pkt_len, 0,
157+
(struct sockaddr *) sll, sizeof(*sll));
163158
if (nbytes < 0) {
164159
E("ERROR: sendto(): %s", strerror(errno));
165160
return -1;
@@ -172,7 +167,7 @@ static int send_http(struct sockaddr *saddr, struct sockaddr *daddr,
172167
static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
173168
struct nfq_data *nfa, void *data)
174169
{
175-
uint32_t pkt_id, ack_new;
170+
uint32_t pkt_id, ifindex, ack_new;
176171
uint16_t ethertype;
177172
int res, i, pkt_len, tcp_payload_len;
178173
struct nfqnl_msg_packet_hdr *ph;
@@ -181,6 +176,8 @@ static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
181176
char src_ip[INET6_ADDRSTRLEN], dst_ip[INET6_ADDRSTRLEN];
182177
struct sockaddr_storage saddr_store, daddr_store;
183178
struct sockaddr *saddr, *daddr;
179+
struct nfqnl_msg_packet_hw *hwph;
180+
struct sockaddr_ll sll;
184181

185182
(void) nfmsg;
186183
(void) data;
@@ -195,14 +192,27 @@ static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
195192
}
196193

197194
pkt_id = ntohl(ph->packet_id);
198-
ethertype = ntohs(ph->hw_protocol);
195+
196+
hwph = nfq_get_packet_hw(nfa);
197+
if (!hwph) {
198+
EE("ERROR: nfq_get_packet_hw(): %s", "failure");
199+
goto ret_accept;
200+
}
201+
202+
ifindex = nfq_get_indev(nfa);
203+
if (!ifindex) {
204+
EE("ERROR: nfq_get_indev(): %s", "failure");
205+
goto ret_accept;
206+
}
207+
199208
pkt_data = NULL;
200209
pkt_len = nfq_get_payload(nfa, &pkt_data);
201210
if (pkt_len < 0 || !pkt_data) {
202211
EE("ERROR: nfq_get_payload(): %s", "failure");
203212
goto ret_accept;
204213
}
205214

215+
ethertype = ntohs(ph->hw_protocol);
206216
if (ethertype == ETHERTYPE_IP) {
207217
res = fh_pkt4_parse(pkt_data, pkt_len, saddr, daddr, &tcph,
208218
&tcp_payload_len);
@@ -222,6 +232,13 @@ static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
222232
goto ret_accept;
223233
}
224234

235+
memset(&sll, 0, sizeof(sll));
236+
sll.sll_family = AF_PACKET;
237+
sll.sll_protocol = ph->hw_protocol;
238+
sll.sll_ifindex = ifindex;
239+
sll.sll_halen = sizeof(hwph->hw_addr);
240+
memcpy(sll.sll_addr, hwph->hw_addr, sizeof(hwph->hw_addr));
241+
225242
if (!g_ctx.silent) {
226243
ipaddr_to_str(saddr, src_ip);
227244
ipaddr_to_str(daddr, dst_ip);
@@ -240,7 +257,7 @@ static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
240257
ack_new = htonl(ack_new);
241258

242259
for (i = 0; i < g_ctx.repeat; i++) {
243-
res = send_ack(daddr, saddr, tcph->dest, tcph->source,
260+
res = send_ack(&sll, daddr, saddr, tcph->dest, tcph->source,
244261
tcph->ack_seq, ack_new);
245262
if (res < 0) {
246263
EE(T(send_ack));
@@ -251,7 +268,7 @@ static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
251268
dst_ip, ntohs(tcph->dest));
252269

253270
for (i = 0; i < g_ctx.repeat; i++) {
254-
res = send_http(daddr, saddr, tcph->dest, tcph->source,
271+
res = send_http(&sll, daddr, saddr, tcph->dest, tcph->source,
255272
tcph->ack_seq, ack_new);
256273
if (res < 0) {
257274
EE(T(send_http));
@@ -267,7 +284,7 @@ static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
267284
ntohs(tcph->dest));
268285

269286
for (i = 0; i < g_ctx.repeat; i++) {
270-
res = send_http(daddr, saddr, tcph->dest, tcph->source,
287+
res = send_http(&sll, daddr, saddr, tcph->dest, tcph->source,
271288
tcph->ack_seq, tcph->seq);
272289
if (res < 0) {
273290
EE(T(send_http));

src/rawsock.c

Lines changed: 17 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,18 @@
2424
#include <string.h>
2525
#include <unistd.h>
2626
#include <arpa/inet.h>
27+
#include <net/ethernet.h>
2728
#include <sys/socket.h>
2829

2930
#include "globvar.h"
3031
#include "logging.h"
3132

32-
int fh_rawsock_setup(int af)
33+
int fh_rawsock_setup(void)
3334
{
3435
int res, opt, sock_fd;
3536
const char *err_hint;
3637

37-
sock_fd = socket(af, SOCK_RAW, IPPROTO_RAW);
38+
sock_fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL));
3839
if (sock_fd < 0) {
3940
switch (errno) {
4041
case EPERM:
@@ -47,36 +48,6 @@ int fh_rawsock_setup(int af)
4748
return -1;
4849
}
4950

50-
res = setsockopt(sock_fd, SOL_SOCKET, SO_BINDTODEVICE, g_ctx.iface,
51-
strlen(g_ctx.iface));
52-
if (res < 0) {
53-
E("ERROR: setsockopt(): SO_BINDTODEVICE: %s", strerror(errno));
54-
goto close_socket;
55-
}
56-
57-
if (af == AF_INET6) {
58-
opt = 1;
59-
res = setsockopt(sock_fd, IPPROTO_IPV6, IPV6_HDRINCL, &opt,
60-
sizeof(opt));
61-
if (res < 0 && errno != ENOPROTOOPT) {
62-
/*
63-
ENOPROTOOPT may occur when kernel version < 4.5.
64-
However, on Linux, IPPROTO_RAW means the kernel will not add a
65-
Layer 3 header, so it is safe to ignore this error.
66-
See raw(7) for details.
67-
*/
68-
E("ERROR: setsockopt(): IPV6_HDRINCL: %s", strerror(errno));
69-
goto close_socket;
70-
}
71-
} else {
72-
opt = 1;
73-
res = setsockopt(sock_fd, IPPROTO_IP, IP_HDRINCL, &opt, sizeof(opt));
74-
if (res < 0) {
75-
E("ERROR: setsockopt(): IP_HDRINCL: %s", strerror(errno));
76-
goto close_socket;
77-
}
78-
}
79-
8051
res = setsockopt(sock_fd, SOL_SOCKET, SO_MARK, &g_ctx.fwmark,
8152
sizeof(g_ctx.fwmark));
8253
if (res < 0) {
@@ -91,12 +62,19 @@ int fh_rawsock_setup(int af)
9162
goto close_socket;
9263
}
9364

94-
if (af == AF_INET6) {
95-
g_ctx.sock6fd = sock_fd;
96-
} else {
97-
g_ctx.sock4fd = sock_fd;
65+
/*
66+
Set SO_RCVBUF to the minimum, since we never call recvfrom() on this
67+
socket.
68+
*/
69+
opt = 128;
70+
res = setsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
71+
if (res < 0) {
72+
E("ERROR: setsockopt(): SO_PRIORITY: %s", strerror(errno));
73+
goto close_socket;
9874
}
9975

76+
g_ctx.sockfd = sock_fd;
77+
10078
return 0;
10179

10280
close_socket:
@@ -108,13 +86,8 @@ int fh_rawsock_setup(int af)
10886

10987
void fh_rawsock_cleanup(void)
11088
{
111-
if (g_ctx.sock4fd >= 0) {
112-
close(g_ctx.sock4fd);
113-
g_ctx.sock4fd = -1;
114-
}
115-
116-
if (g_ctx.sock6fd >= 0) {
117-
close(g_ctx.sock6fd);
118-
g_ctx.sock6fd = -1;
89+
if (g_ctx.sockfd >= 0) {
90+
close(g_ctx.sockfd);
91+
g_ctx.sockfd = -1;
11992
}
12093
}

0 commit comments

Comments
 (0)