1
1
/*
2
- * fakehttp_nfq .c - FakeHTTP_NFQ
2
+ * fakehttp .c - FakeHTTP: https://github.com/MikeWang000000/FakeHTTP
3
3
*
4
4
* Copyright (C) 2025 MikeWang000000
5
5
*
19
19
20
20
#define _GNU_SOURCE
21
21
#include <errno.h>
22
+ #include <fcntl.h>
23
+ #include <inttypes.h>
22
24
#include <limits.h>
23
25
#include <stdarg.h>
24
26
#include <stdint.h>
30
32
#include <arpa/inet.h>
31
33
#include <netinet/ip.h>
32
34
#include <netinet/tcp.h>
35
+ #include <sys/wait.h>
33
36
#include <linux/netfilter.h>
34
37
#include <linux/netfilter/nfnetlink_queue.h>
35
38
#include <libnetfilter_queue/libnetfilter_queue.h>
36
39
37
- #define VERSION "0.9.1 "
40
+ #define VERSION "0.9.2 "
38
41
39
42
#define E (...) logger(__func__, __FILE__, __LINE__, __VA_ARGS__)
40
43
41
44
static int g_sockfd = 0 ;
42
- static int g_chkonly = 0 ;
45
+ static int g_exit = 0 ;
43
46
static int g_repeat = 3 ;
44
47
static uint32_t g_fwmark = 512 ;
45
48
static uint32_t g_nfqnum = 512 ;
@@ -49,15 +52,10 @@ static const char *g_hostname = NULL;
49
52
50
53
static void print_usage (const char * name )
51
54
{
52
- if (g_chkonly ) {
53
- return ;
54
- }
55
-
56
55
fprintf (stderr ,
57
56
"Usage: %s [options]\n"
58
57
"\n"
59
58
"Options:\n"
60
- " -c check options and exit\n"
61
59
" -h <hostname> hostname for obfuscation (required)\n"
62
60
" -i <interface> either interface name (required)\n"
63
61
" -m <mark> fwmark for bypassing the queue\n"
@@ -66,7 +64,7 @@ static void print_usage(const char *name)
66
64
"times\n"
67
65
" -t <ttl> TTL for generated packets\n"
68
66
"\n"
69
- "FakeHTTP_NFQ version " VERSION "\n" ,
67
+ "FakeHTTP version " VERSION "\n" ,
70
68
name );
71
69
}
72
70
@@ -94,6 +92,219 @@ static void logger(const char *funcname, const char *filename,
94
92
}
95
93
96
94
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
+
97
308
static uint16_t chksum (void * pseudo , size_t pseudo_count , void * data ,
98
309
size_t count )
99
310
{
@@ -423,11 +634,8 @@ int main(int argc, char *argv[])
423
634
return EXIT_FAILURE ;
424
635
}
425
636
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 ) {
427
638
switch (opt ) {
428
- case 'c' :
429
- g_chkonly = 1 ;
430
- break ;
431
639
case 'h' :
432
640
if (strlen (optarg ) > _POSIX_HOST_NAME_MAX ) {
433
641
fprintf (stderr , "%s: hostname is too long.\n" , argv [0 ]);
@@ -497,9 +705,7 @@ int main(int argc, char *argv[])
497
705
return EXIT_FAILURE ;
498
706
}
499
707
500
- if (!g_chkonly ) {
501
- E ("FakeHTTP version " VERSION );
502
- }
708
+ E ("FakeHTTP version " VERSION );
503
709
504
710
srand (time (NULL ));
505
711
@@ -574,22 +780,37 @@ int main(int argc, char *argv[])
574
780
575
781
fd = nfq_fd (h );
576
782
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 ;
580
800
}
581
801
582
802
/*
583
803
Main Loop
584
804
*/
585
- for (;; ) {
805
+ while (! g_exit ) {
586
806
recv_len = recv (fd , buff , buffsize , 0 );
587
807
if (recv_len < 0 ) {
588
808
if (errno == EINTR ) {
589
- continue ;
809
+ g_exit = 1 ;
810
+ goto exit_success ;
590
811
}
591
812
E ("ERROR: recv(): %s" , strerror (errno ));
592
- goto destroy_queue ;
813
+ goto cleanup_iptables ;
593
814
}
594
815
res = nfq_handle_packet (h , buff , recv_len );
595
816
if (res < 0 ) {
@@ -598,6 +819,13 @@ int main(int argc, char *argv[])
598
819
}
599
820
}
600
821
822
+ exit_success :
823
+ E ("exiting normally..." );
824
+ exitcode = EXIT_SUCCESS ;
825
+
826
+ cleanup_iptables :
827
+ ipt_rules_cleanup ();
828
+
601
829
destroy_queue :
602
830
nfq_destroy_queue (qh );
603
831
0 commit comments