Skip to content

Commit f422703

Browse files
feat: make fakehttp single file
1 parent 7bda269 commit f422703

File tree

3 files changed

+252
-228
lines changed

3 files changed

+252
-228
lines changed

Makefile

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,26 @@ BINDIR=$(PREFIX)/bin
1010
BUILDDIR=build
1111

1212
FAKEHTTP=$(BUILDDIR)/fakehttp
13-
FAKEHTTP_NFQ=$(BUILDDIR)/fakehttp_nfq
1413

1514
ifeq ($(STATIC), 1)
1615
override CFLAGS += -static
1716
endif
1817

19-
all: $(FAKEHTTP) $(FAKEHTTP_NFQ)
18+
all: $(FAKEHTTP)
2019

2120
clean:
2221
$(RM) -r $(BUILDDIR)
2322

24-
$(FAKEHTTP): src/fakehttp.sh
25-
mkdir -p $(BUILDDIR)
26-
install -m 755 $< $@
27-
28-
$(FAKEHTTP_NFQ): src/fakehttp_nfq.c
23+
$(FAKEHTTP): src/fakehttp.c
2924
mkdir -p $(BUILDDIR)
3025
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
3126
$(STRIP) $@
3227

3328
install: all
3429
mkdir -p $(DESTDIR)$(BINDIR)
35-
install -m 755 fakehttp_nfq $(DESTDIR)$(BINDIR)/fakehttp_nfq
3630
install -m 755 fakehttp $(DESTDIR)$(BINDIR)/fakehttp
3731

3832
uninstall:
39-
$(RM) $(DESTDIR)$(BINDIR)/fakehttp_nfq
4033
$(RM) $(DESTDIR)$(BINDIR)/fakehttp
4134

4235
.PHONY: all clean install uninstall

src/fakehttp_nfq.c renamed to src/fakehttp.c

Lines changed: 250 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* fakehttp_nfq.c - FakeHTTP_NFQ
2+
* fakehttp.c - FakeHTTP: https://github.com/MikeWang000000/FakeHTTP
33
*
44
* Copyright (C) 2025 MikeWang000000
55
*
@@ -19,6 +19,8 @@
1919

2020
#define _GNU_SOURCE
2121
#include <errno.h>
22+
#include <fcntl.h>
23+
#include <inttypes.h>
2224
#include <limits.h>
2325
#include <stdarg.h>
2426
#include <stdint.h>
@@ -30,16 +32,17 @@
3032
#include <arpa/inet.h>
3133
#include <netinet/ip.h>
3234
#include <netinet/tcp.h>
35+
#include <sys/wait.h>
3336
#include <linux/netfilter.h>
3437
#include <linux/netfilter/nfnetlink_queue.h>
3538
#include <libnetfilter_queue/libnetfilter_queue.h>
3639

37-
#define VERSION "0.9.1"
40+
#define VERSION "0.9.2"
3841

3942
#define E(...) logger(__func__, __FILE__, __LINE__, __VA_ARGS__)
4043

4144
static int g_sockfd = 0;
42-
static int g_chkonly = 0;
45+
static int g_exit = 0;
4346
static int g_repeat = 3;
4447
static uint32_t g_fwmark = 512;
4548
static uint32_t g_nfqnum = 512;
@@ -49,15 +52,10 @@ static const char *g_hostname = NULL;
4952

5053
static void print_usage(const char *name)
5154
{
52-
if (g_chkonly) {
53-
return;
54-
}
55-
5655
fprintf(stderr,
5756
"Usage: %s [options]\n"
5857
"\n"
5958
"Options:\n"
60-
" -c check options and exit\n"
6159
" -h <hostname> hostname for obfuscation (required)\n"
6260
" -i <interface> either interface name (required)\n"
6361
" -m <mark> fwmark for bypassing the queue\n"
@@ -66,7 +64,7 @@ static void print_usage(const char *name)
6664
"times\n"
6765
" -t <ttl> TTL for generated packets\n"
6866
"\n"
69-
"FakeHTTP_NFQ version " VERSION "\n",
67+
"FakeHTTP version " VERSION "\n",
7068
name);
7169
}
7270

@@ -94,6 +92,219 @@ static void logger(const char *funcname, const char *filename,
9492
}
9593

9694

95+
static void signal_handler(int sig)
96+
{
97+
switch (sig) {
98+
case SIGINT:
99+
case SIGTERM:
100+
g_exit = 1;
101+
break;
102+
default:
103+
break;
104+
}
105+
}
106+
107+
108+
static int signal_setup(void)
109+
{
110+
struct sigaction sa;
111+
int res;
112+
113+
memset(&sa, 0, sizeof(sa));
114+
sa.sa_handler = SIG_IGN;
115+
116+
res = sigaction(SIGPIPE, &sa, NULL);
117+
if (res < 0) {
118+
E("ERROR: sigaction(): %s", strerror(errno));
119+
return -1;
120+
}
121+
122+
res = sigaction(SIGHUP, &sa, NULL);
123+
if (res < 0) {
124+
E("ERROR: sigaction(): %s", strerror(errno));
125+
return -1;
126+
}
127+
128+
sa.sa_handler = signal_handler;
129+
130+
res = sigaction(SIGINT, &sa, NULL);
131+
if (res < 0) {
132+
E("ERROR: sigaction(): %s", strerror(errno));
133+
return -1;
134+
}
135+
136+
res = sigaction(SIGTERM, &sa, NULL);
137+
if (res < 0) {
138+
E("ERROR: sigaction(): %s", strerror(errno));
139+
return -1;
140+
}
141+
142+
return 0;
143+
}
144+
145+
146+
static int execute_command(char **argv, int silent)
147+
{
148+
int res, status, fd, i;
149+
pid_t pid;
150+
151+
pid = fork();
152+
if (pid < 0) {
153+
E("ERROR: fork(): %s", strerror(errno));
154+
return -1;
155+
}
156+
157+
if (!pid) {
158+
if (silent) {
159+
fd = open("/dev/null", O_WRONLY);
160+
if (fd < 0) {
161+
E("ERROR: open(): %s", strerror(errno));
162+
_exit(EXIT_FAILURE);
163+
}
164+
res = dup2(fd, STDOUT_FILENO);
165+
if (res < 0) {
166+
E("ERROR: dup2(): %s", strerror(errno));
167+
_exit(EXIT_FAILURE);
168+
}
169+
res = dup2(fd, STDERR_FILENO);
170+
if (res < 0) {
171+
E("ERROR: dup2(): %s", strerror(errno));
172+
_exit(EXIT_FAILURE);
173+
}
174+
close(fd);
175+
}
176+
177+
execvp(argv[0], argv);
178+
179+
E("ERROR: execvp(): %s", strerror(errno));
180+
fprintf(stderr, "failed to execute: %s", argv[0]);
181+
for (i = 1; argv[i]; i++) {
182+
fprintf(stderr, " %s", argv[i]);
183+
}
184+
fputc('\n', stderr);
185+
fflush(stderr);
186+
187+
_exit(EXIT_FAILURE);
188+
}
189+
190+
if (waitpid(pid, &status, 0) < 0) {
191+
E("ERROR: waitpid(): %s", strerror(errno));
192+
return -1;
193+
}
194+
195+
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
196+
return 0;
197+
}
198+
199+
return -1;
200+
}
201+
202+
203+
static void ipt_rules_cleanup(void)
204+
{
205+
size_t i, ipt_cmds_cnt;
206+
char *ipt_cmds[][32] = {
207+
{"iptables", "-t", "mangle", "-F", "FAKEHTTP", NULL},
208+
{"iptables", "-t", "mangle", "-D", "INPUT", "-j", "FAKEHTTP", NULL},
209+
{"iptables", "-t", "mangle", "-D", "FORWARD", "-j", "FAKEHTTP", NULL},
210+
{"iptables", "-t", "mangle", "-X", "FAKEHTTP", NULL}};
211+
212+
ipt_cmds_cnt = sizeof(ipt_cmds) / sizeof(*ipt_cmds);
213+
214+
for (i = 0; i < ipt_cmds_cnt; i++) {
215+
execute_command(ipt_cmds[i], 1);
216+
}
217+
}
218+
219+
220+
static int ipt_rules_setup(void)
221+
{
222+
char fwmark_str[32], nfqnum_str[32], iface_str[32];
223+
size_t i, ipt_cmds_cnt;
224+
int res;
225+
char *ipt_cmds[][32] = {
226+
{"iptables", "-t", "mangle", "-N", "FAKEHTTP", NULL},
227+
{"iptables", "-t", "mangle", "-I", "INPUT", "-j", "FAKEHTTP", NULL},
228+
{"iptables", "-t", "mangle", "-I", "FORWARD", "-j", "FAKEHTTP", NULL},
229+
230+
/*
231+
exclude marked packets
232+
*/
233+
{"iptables", "-t", "mangle", "-A", "FAKEHTTP", "-m", "mark", "--mark",
234+
fwmark_str, "-j", "CONNMARK", "--save-mark", NULL},
235+
236+
{"iptables", "-t", "mangle", "-A", "FAKEHTTP", "-m", "connmark",
237+
"--mark", fwmark_str, "-j", "CONNMARK", "--restore-mark", NULL},
238+
239+
{"iptables", "-t", "mangle", "-A", "FAKEHTTP", "-m", "mark", "--mark",
240+
fwmark_str, "-j", "RETURN", NULL},
241+
242+
/*
243+
exclude local IPs
244+
*/
245+
{"iptables", "-t", "mangle", "-A", "FAKEHTTP", "-s", "0.0.0.0/8", "-j",
246+
"RETURN", NULL},
247+
248+
{"iptables", "-t", "mangle", "-A", "FAKEHTTP", "-s", "10.0.0.0/8",
249+
"-j", "RETURN", NULL},
250+
251+
{"iptables", "-t", "mangle", "-A", "FAKEHTTP", "-s", "100.64.0.0/10",
252+
"-j", "RETURN", NULL},
253+
254+
{"iptables", "-t", "mangle", "-A", "FAKEHTTP", "-s", "127.0.0.0/8",
255+
"-j", "RETURN", NULL},
256+
257+
{"iptables", "-t", "mangle", "-A", "FAKEHTTP", "-s", "169.254.0.0/16",
258+
"-j", "RETURN", NULL},
259+
260+
{"iptables", "-t", "mangle", "-A", "FAKEHTTP", "-s", "172.16.0.0/12",
261+
"-j", "RETURN", NULL},
262+
263+
{"iptables", "-t", "mangle", "-A", "FAKEHTTP", "-s", "192.168.0.0/16",
264+
"-j", "RETURN", NULL},
265+
266+
{"iptables", "-t", "mangle", "-A", "FAKEHTTP", "-s", "224.0.0.0/3",
267+
"-j", "RETURN", NULL},
268+
269+
/*
270+
send to nfqueue
271+
*/
272+
{"iptables", "-t", "mangle", "-A", "FAKEHTTP", "-i", iface_str, "-p",
273+
"tcp", "--tcp-flags", "ACK,FIN,RST", "ACK", "-j", "NFQUEUE",
274+
"--queue-num", nfqnum_str, NULL}};
275+
276+
ipt_cmds_cnt = sizeof(ipt_cmds) / sizeof(*ipt_cmds);
277+
278+
res = snprintf(fwmark_str, sizeof(fwmark_str), "%" PRIu32, g_fwmark);
279+
if (res < 0 || (size_t) res >= sizeof(fwmark_str)) {
280+
E("ERROR: snprintf()");
281+
return -1;
282+
}
283+
284+
res = snprintf(nfqnum_str, sizeof(nfqnum_str), "%" PRIu32, g_nfqnum);
285+
if (res < 0 || (size_t) res >= sizeof(nfqnum_str)) {
286+
E("ERROR: snprintf()");
287+
return -1;
288+
}
289+
290+
res = snprintf(iface_str, sizeof(iface_str), "%s", g_iface);
291+
if (res < 0 || (size_t) res >= sizeof(iface_str)) {
292+
E("ERROR: snprintf()");
293+
return -1;
294+
}
295+
296+
for (i = 0; i < ipt_cmds_cnt; i++) {
297+
res = execute_command(ipt_cmds[i], 0);
298+
if (res) {
299+
E("ERROR: execute_command()");
300+
return -1;
301+
}
302+
}
303+
304+
return 0;
305+
}
306+
307+
97308
static uint16_t chksum(void *pseudo, size_t pseudo_count, void *data,
98309
size_t count)
99310
{
@@ -423,11 +634,8 @@ int main(int argc, char *argv[])
423634
return EXIT_FAILURE;
424635
}
425636

426-
while ((opt = getopt(argc, argv, "ch:i:m:n:r:t:")) != -1) {
637+
while ((opt = getopt(argc, argv, "h:i:m:n:r:t:")) != -1) {
427638
switch (opt) {
428-
case 'c':
429-
g_chkonly = 1;
430-
break;
431639
case 'h':
432640
if (strlen(optarg) > _POSIX_HOST_NAME_MAX) {
433641
fprintf(stderr, "%s: hostname is too long.\n", argv[0]);
@@ -497,9 +705,7 @@ int main(int argc, char *argv[])
497705
return EXIT_FAILURE;
498706
}
499707

500-
if (!g_chkonly) {
501-
E("FakeHTTP version " VERSION);
502-
}
708+
E("FakeHTTP version " VERSION);
503709

504710
srand(time(NULL));
505711

@@ -574,22 +780,37 @@ int main(int argc, char *argv[])
574780

575781
fd = nfq_fd(h);
576782

577-
if (g_chkonly) {
578-
exitcode = EXIT_SUCCESS;
579-
goto destroy_queue;
783+
/*
784+
Iptables
785+
*/
786+
ipt_rules_cleanup();
787+
res = ipt_rules_setup();
788+
if (res) {
789+
E("ERROR: ipt_rules_setup()");
790+
goto cleanup_iptables;
791+
}
792+
793+
/*
794+
Signals
795+
*/
796+
res = signal_setup();
797+
if (res) {
798+
E("ERROR: signal_setup()");
799+
goto cleanup_iptables;
580800
}
581801

582802
/*
583803
Main Loop
584804
*/
585-
for (;;) {
805+
while (!g_exit) {
586806
recv_len = recv(fd, buff, buffsize, 0);
587807
if (recv_len < 0) {
588808
if (errno == EINTR) {
589-
continue;
809+
g_exit = 1;
810+
goto exit_success;
590811
}
591812
E("ERROR: recv(): %s", strerror(errno));
592-
goto destroy_queue;
813+
goto cleanup_iptables;
593814
}
594815
res = nfq_handle_packet(h, buff, recv_len);
595816
if (res < 0) {
@@ -598,6 +819,13 @@ int main(int argc, char *argv[])
598819
}
599820
}
600821

822+
exit_success:
823+
E("exiting normally...");
824+
exitcode = EXIT_SUCCESS;
825+
826+
cleanup_iptables:
827+
ipt_rules_cleanup();
828+
601829
destroy_queue:
602830
nfq_destroy_queue(qh);
603831

0 commit comments

Comments
 (0)