Skip to content

Commit ff2021f

Browse files
feat: Add support for dynamic TTL
1 parent 7af5835 commit ff2021f

File tree

9 files changed

+59
-28
lines changed

9 files changed

+59
-28
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Advanced Options:
4141
-r <repeat> duplicate generated packets for <repeat> times
4242
-t <ttl> TTL for generated packets
4343
-x <mask> set the mask for fwmark
44+
-y <pct> raise TTL dynamically to <pct>% of estimated hops
4445
-z use iptables commands instead of nft
4546
4647
```

include/globvar.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct fh_context {
4545
/* -t */ uint8_t ttl;
4646
/* -w */ const char *logpath;
4747
/* -x */ uint32_t fwmask;
48+
/* -y */ int dynamic_pct;
4849
/* -z */ int use_iptables;
4950
};
5051

include/ipv4pkt.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ int fh_pkt4_parse(void *pkt_data, int pkt_len, struct sockaddr *saddr,
2929
struct tcphdr **tcph_ptr, int *tcp_payload_len);
3030

3131
int fh_pkt4_make(char *buffer, size_t buffer_size, struct sockaddr *saddr,
32-
struct sockaddr *daddr, uint16_t sport_be, uint16_t dport_be,
33-
uint32_t seq_be, uint32_t ackseq_be, int psh,
34-
char *tcp_payload, size_t tcp_payload_size);
32+
struct sockaddr *daddr, uint8_t ttl, uint16_t sport_be,
33+
uint16_t dport_be, uint32_t seq_be, uint32_t ackseq_be,
34+
int psh, char *tcp_payload, size_t tcp_payload_size);
3535

3636
#endif /* FH_IPV4PKT_H */

include/ipv6pkt.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ int fh_pkt6_parse(void *pkt_data, int pkt_len, struct sockaddr *saddr,
2929
struct tcphdr **tcph_ptr, int *tcp_payload_len);
3030

3131
int fh_pkt6_make(char *buffer, size_t buffer_size, struct sockaddr *saddr,
32-
struct sockaddr *daddr, uint16_t sport_be, uint16_t dport_be,
33-
uint32_t seq_be, uint32_t ackseq_be, int psh,
34-
char *tcp_payload, size_t tcp_payload_size);
32+
struct sockaddr *daddr, uint8_t ttl, uint16_t sport_be,
33+
uint16_t dport_be, uint32_t seq_be, uint32_t ackseq_be,
34+
int psh, char *tcp_payload, size_t tcp_payload_size);
3535

3636
#endif /* FH_IPV6PKT_H */

src/globvar.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,5 @@ struct fh_context g_ctx = {.exit = 0,
4545
/* -t */ .ttl = 3,
4646
/* -w */ .logpath = NULL,
4747
/* -x */ .fwmask = 0,
48+
/* -y */ .dynamic_pct = 0,
4849
/* -z */ .use_iptables = 0};

src/ipv4pkt.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ int fh_pkt4_parse(void *pkt_data, int pkt_len, struct sockaddr *saddr,
9292

9393

9494
int fh_pkt4_make(char *buffer, size_t buffer_size, struct sockaddr *saddr,
95-
struct sockaddr *daddr, uint16_t sport_be, uint16_t dport_be,
96-
uint32_t seq_be, uint32_t ackseq_be, int psh,
97-
char *tcp_payload, size_t tcp_payload_size)
95+
struct sockaddr *daddr, uint8_t ttl, uint16_t sport_be,
96+
uint16_t dport_be, uint32_t seq_be, uint32_t ackseq_be,
97+
int psh, char *tcp_payload, size_t tcp_payload_size)
9898
{
9999
size_t pkt_len;
100100
struct iphdr *iph;
@@ -127,7 +127,7 @@ int fh_pkt4_make(char *buffer, size_t buffer_size, struct sockaddr *saddr,
127127
iph->tot_len = htons(pkt_len);
128128
iph->id = ((rand() & 0xff) << 8) | (rand() & 0xff);
129129
iph->frag_off = htons(1 << 14 /* DF */);
130-
iph->ttl = g_ctx.ttl;
130+
iph->ttl = ttl;
131131
iph->protocol = IPPROTO_TCP;
132132
iph->check = 0;
133133
iph->saddr = saddr_in->sin_addr.s_addr;

src/ipv6pkt.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,9 @@ int fh_pkt6_parse(void *pkt_data, int pkt_len, struct sockaddr *saddr,
8888

8989

9090
int fh_pkt6_make(char *buffer, size_t buffer_size, struct sockaddr *saddr,
91-
struct sockaddr *daddr, uint16_t sport_be, uint16_t dport_be,
92-
uint32_t seq_be, uint32_t ackseq_be, int psh,
93-
char *tcp_payload, size_t tcp_payload_size)
91+
struct sockaddr *daddr, uint8_t ttl, uint16_t sport_be,
92+
uint16_t dport_be, uint32_t seq_be, uint32_t ackseq_be,
93+
int psh, char *tcp_payload, size_t tcp_payload_size)
9494
{
9595
size_t pkt_len;
9696
struct ip6_hdr *ip6h;
@@ -121,7 +121,7 @@ int fh_pkt6_make(char *buffer, size_t buffer_size, struct sockaddr *saddr,
121121
0 /* flow */);
122122
ip6h->ip6_plen = htons(sizeof(*tcph) + tcp_payload_size);
123123
ip6h->ip6_nxt = IPPROTO_TCP;
124-
ip6h->ip6_hops = g_ctx.ttl;
124+
ip6h->ip6_hops = ttl;
125125
memcpy(&ip6h->ip6_src, &saddr_in6->sin6_addr, sizeof(struct in6_addr));
126126
memcpy(&ip6h->ip6_dst, &daddr_in6->sin6_addr, sizeof(struct in6_addr));
127127

src/mainfun.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ static void print_usage(const char *name)
7777
" -r <repeat> duplicate generated packets for <repeat> times\n"
7878
" -t <ttl> TTL for generated packets\n"
7979
" -x <mask> set the mask for fwmark\n"
80+
" -y <pct> raise TTL dynamically to <pct>%% of estimated "
81+
"hops\n"
8082
" -z use iptables commands instead of nft\n"
8183
"\n"
8284
"FakeHTTP version " VERSION "\n";
@@ -104,7 +106,8 @@ int main(int argc, char *argv[])
104106
memset(g_ctx.iface, 0, sizeof(g_ctx.iface));
105107
exitcode = EXIT_FAILURE;
106108

107-
while ((opt = getopt(argc, argv, "0146ab:dfgh:i:km:n:r:st:w:x:z")) != -1) {
109+
while ((opt = getopt(argc, argv, "0146ab:dfgh:i:km:n:r:st:w:x:y:z")) !=
110+
-1) {
108111
switch (opt) {
109112
case '0':
110113
g_ctx.inbound = 1;
@@ -251,6 +254,16 @@ int main(int argc, char *argv[])
251254
g_ctx.fwmask = tmp;
252255
break;
253256

257+
case 'y':
258+
tmp = strtoull(optarg, NULL, 0);
259+
if (!tmp || tmp >= 100) {
260+
fprintf(stderr, "%s: invalid value for -y.\n", argv[0]);
261+
print_usage(argv[0]);
262+
return EXIT_FAILURE;
263+
}
264+
g_ctx.dynamic_pct = tmp;
265+
break;
266+
254267
case 'z':
255268
g_ctx.use_iptables = 1;
256269
break;
@@ -301,6 +314,12 @@ int main(int argc, char *argv[])
301314
return EXIT_FAILURE;
302315
}
303316

317+
if (g_ctx.dynamic_pct && g_ctx.nohopest) {
318+
fprintf(stderr, "%s: option -y cannot be used with -g.\n", argv[0]);
319+
print_usage(argv[0]);
320+
return EXIT_FAILURE;
321+
}
322+
304323
if (g_ctx.daemon) {
305324
res = daemon(0, 0);
306325
if (res < 0) {

src/rawsend.c

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -132,23 +132,23 @@ static int setup_http_buff(void)
132132

133133

134134
static int send_ack(struct sockaddr_ll *sll, struct sockaddr *saddr,
135-
struct sockaddr *daddr, uint16_t sport_be,
135+
struct sockaddr *daddr, uint8_t ttl, uint16_t sport_be,
136136
uint16_t dport_be, uint32_t seq_be, uint32_t ackseq_be)
137137
{
138138
int pkt_len;
139139
ssize_t nbytes;
140140
char pkt_buff[1024];
141141

142142
if (daddr->sa_family == AF_INET) {
143-
pkt_len = fh_pkt4_make(pkt_buff, sizeof(pkt_buff), saddr, daddr,
143+
pkt_len = fh_pkt4_make(pkt_buff, sizeof(pkt_buff), saddr, daddr, ttl,
144144
sport_be, dport_be, seq_be, ackseq_be, 0, NULL,
145145
0);
146146
if (pkt_len < 0) {
147147
E(T(fh_pkt4_make));
148148
return -1;
149149
}
150150
} else if (daddr->sa_family == AF_INET6) {
151-
pkt_len = fh_pkt6_make(pkt_buff, sizeof(pkt_buff), saddr, daddr,
151+
pkt_len = fh_pkt6_make(pkt_buff, sizeof(pkt_buff), saddr, daddr, ttl,
152152
sport_be, dport_be, seq_be, ackseq_be, 0, NULL,
153153
0);
154154
if (pkt_len < 0) {
@@ -172,23 +172,23 @@ static int send_ack(struct sockaddr_ll *sll, struct sockaddr *saddr,
172172

173173

174174
static int send_http(struct sockaddr_ll *sll, struct sockaddr *saddr,
175-
struct sockaddr *daddr, uint16_t sport_be,
175+
struct sockaddr *daddr, uint8_t ttl, uint16_t sport_be,
176176
uint16_t dport_be, uint32_t seq_be, uint32_t ackseq_be)
177177
{
178178
int pkt_len;
179179
ssize_t nbytes;
180180
char pkt_buff[1024];
181181

182182
if (daddr->sa_family == AF_INET) {
183-
pkt_len = fh_pkt4_make(pkt_buff, sizeof(pkt_buff), saddr, daddr,
183+
pkt_len = fh_pkt4_make(pkt_buff, sizeof(pkt_buff), saddr, daddr, ttl,
184184
sport_be, dport_be, seq_be, ackseq_be, 1,
185185
http_buff, http_len);
186186
if (pkt_len < 0) {
187187
E(T(fh_pkt4_make));
188188
return -1;
189189
}
190190
} else if (daddr->sa_family == AF_INET6) {
191-
pkt_len = fh_pkt6_make(pkt_buff, sizeof(pkt_buff), saddr, daddr,
191+
pkt_len = fh_pkt6_make(pkt_buff, sizeof(pkt_buff), saddr, daddr, ttl,
192192
sport_be, dport_be, seq_be, ackseq_be, 1,
193193
http_buff, http_len);
194194
if (pkt_len < 0) {
@@ -296,7 +296,7 @@ int fh_rawsend_handle(struct sockaddr_ll *sll, uint8_t *pkt_data, int pkt_len)
296296
uint32_t ack_new;
297297
uint16_t ethertype;
298298
int res, i, tcp_payload_len, hop;
299-
uint8_t src_ttl;
299+
uint8_t src_ttl, snd_ttl;
300300
struct tcphdr *tcph;
301301
char src_ip[INET6_ADDRSTRLEN], dst_ip[INET6_ADDRSTRLEN];
302302
struct sockaddr_storage saddr_store, daddr_store;
@@ -330,13 +330,22 @@ int fh_rawsend_handle(struct sockaddr_ll *sll, uint8_t *pkt_data, int pkt_len)
330330
ipaddr_to_str(daddr, dst_ip);
331331
}
332332

333+
snd_ttl = 0;
334+
333335
if (!g_ctx.nohopest) {
334336
hop = hop_estimate(src_ttl);
335337
if (hop <= g_ctx.ttl) {
336338
E_INFO("%s:%u ===LOCAL(?)===> %s:%u", src_ip, ntohs(tcph->source),
337339
dst_ip, ntohs(tcph->dest));
338340
return 0;
339341
}
342+
if (g_ctx.dynamic_pct) {
343+
snd_ttl = hop * g_ctx.dynamic_pct / 100;
344+
}
345+
}
346+
347+
if (snd_ttl < g_ctx.ttl) {
348+
snd_ttl = g_ctx.ttl;
340349
}
341350

342351
if (tcp_payload_len > 0) {
@@ -358,8 +367,8 @@ int fh_rawsend_handle(struct sockaddr_ll *sll, uint8_t *pkt_data, int pkt_len)
358367
ack_new = htonl(ack_new);
359368

360369
for (i = 0; i < g_ctx.repeat; i++) {
361-
res = send_ack(sll, daddr, saddr, tcph->dest, tcph->source,
362-
tcph->ack_seq, ack_new);
370+
res = send_ack(sll, daddr, saddr, snd_ttl, tcph->dest,
371+
tcph->source, tcph->ack_seq, ack_new);
363372
if (res < 0) {
364373
E(T(send_ack));
365374
return -1;
@@ -369,8 +378,8 @@ int fh_rawsend_handle(struct sockaddr_ll *sll, uint8_t *pkt_data, int pkt_len)
369378
dst_ip, ntohs(tcph->dest));
370379

371380
for (i = 0; i < g_ctx.repeat; i++) {
372-
res = send_http(sll, daddr, saddr, tcph->dest, tcph->source,
373-
tcph->ack_seq, ack_new);
381+
res = send_http(sll, daddr, saddr, snd_ttl, tcph->dest,
382+
tcph->source, tcph->ack_seq, ack_new);
374383
if (res < 0) {
375384
E(T(send_http));
376385
return -1;
@@ -391,8 +400,8 @@ int fh_rawsend_handle(struct sockaddr_ll *sll, uint8_t *pkt_data, int pkt_len)
391400
ntohs(tcph->dest));
392401

393402
for (i = 0; i < g_ctx.repeat; i++) {
394-
res = send_http(sll, daddr, saddr, tcph->dest, tcph->source,
395-
tcph->ack_seq, tcph->seq);
403+
res = send_http(sll, daddr, saddr, snd_ttl, tcph->dest,
404+
tcph->source, tcph->ack_seq, tcph->seq);
396405
if (res < 0) {
397406
E(T(send_http));
398407
return -1;

0 commit comments

Comments
 (0)