Skip to content

Commit

Permalink
UDP faking support
Browse files Browse the repository at this point in the history
  • Loading branch information
Waujito committed Dec 4, 2024
1 parent 5ee77d5 commit b2ac2e0
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 30 deletions.
3 changes: 2 additions & 1 deletion config.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,9 @@ for (struct section_config_t *section = &config.default_config + config.custom_c
#define FAKE_STRAT_PAST_SEQ (1 << 2)
#define FAKE_STRAT_TCP_CHECK (1 << 3)
#define FAKE_STRAT_TCP_MD5SUM (1 << 4)
#define FAKE_STRAT_UDP_CHECK (1 << 5)

#define FAKE_STRAT_COUNT 5
#define FAKE_STRAT_COUNT 6

/**
* This macros iterates through all faking strategies and executes code under it.
Expand Down
81 changes: 52 additions & 29 deletions mangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,32 @@ int process_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
break;
}

if (verdict == PKT_CONTINUE)
if (verdict == PKT_CONTINUE) {
lgtrace_addp("continue_flow");
continue;
}

lgtrace_end();
return verdict;
goto ret_verdict;
}

accept:
verdict = PKT_ACCEPT;

ret_verdict:

switch (verdict) {
case PKT_ACCEPT:
lgtrace_addp("accept");
break;
case PKT_DROP:
lgtrace_addp("drop");
break;
default:
lgtrace_addp("unknow verdict: %d", verdict);
}
lgtrace_end();
return PKT_ACCEPT;

return verdict;
}

int process_tcp_packet(const struct section_config_t *section, const uint8_t *raw_payload, uint32_t raw_payload_len) {
Expand Down Expand Up @@ -309,13 +325,10 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
}

continue_flow:
lgtrace_addp("continue_flow");
return PKT_CONTINUE;
accept:
lgtrace_addp("accept");
return PKT_ACCEPT;
drop:
lgtrace_addp("drop");
return PKT_DROP;
}

Expand Down Expand Up @@ -350,6 +363,7 @@ int process_udp_packet(const struct section_config_t *section, const uint8_t *pk
}



if (section->quic_drop) {
lgtrace_addp("QUIC probe");
const struct quic_lhdr *qch;
Expand Down Expand Up @@ -384,39 +398,48 @@ int process_udp_packet(const struct section_config_t *section, const uint8_t *pk
lgtrace_addp("quic initial message");
}

/*
if (1) {
lgtrace_addp("Probe udp");
if (ipver == IP4VERSION && ntohs(udph->dest) > 30) {
lgtrace_addp("udp fool");
const uint8_t *payload;
uint32_t payload_len;
uint32_t poses[10];
int cnt = 3;
poses[0] = 8;
for (int i = 1; i < cnt; i++) {
poses[i] = poses[i - 1] + 8;
for (int i = 0; i < 6; i++) {
NETBUF_ALLOC(fake_udp, MAX_PACKET_SIZE);
if (!NETBUF_CHECK(fake_udp)) {
lgerror(-ENOMEM, "Allocation error");
return -ENOMEM;
}
uint32_t fsn_len = MAX_PACKET_SIZE;

ret = send_ip4_frags(pkt, pktlen, poses, cnt, 0);
struct udp_fake_type fake_type = {
.fake_len = 64,
.strategy = {
.strategy = FAKE_STRAT_UDP_CHECK,
},
};
ret = gen_fake_udp(fake_type, iph, iph_len, udph, fake_udp, &fsn_len);
if (ret < 0) {
lgerror("ip4 send frags", ret);
goto accept;
lgerror(ret, "gen_fake_udp");
goto erret_lc;
}

goto drop;
} else {
lginfo("WARNING: IP fragmentation is supported only for IPv4\n");
lgtrace_addp("post fake udp #%d", i + 1);

ret = instance_config.send_raw_packet(fake_udp, fsn_len);
if (ret < 0) {
lgerror(ret, "send fake udp");
goto erret_lc;
}

NETBUF_FREE(fake_udp);
continue;
erret_lc:
NETBUF_FREE(fake_udp);
goto accept;
}
}
*/


ret = instance_config.send_raw_packet(pkt, pktlen);
goto drop;
}

continue_flow:
lgtrace_addp("continue_flow");
return PKT_CONTINUE;
accept_quic:
accept:
Expand Down
109 changes: 109 additions & 0 deletions quic.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,112 @@ int quic_parse_initial_message(uint8_t *inpayload, uint32_t inplen,
lgerror(-EINVAL, "QUIC invalid Initial packet");
return -EINVAL;
}

int udp_fail_packet(struct udp_failing_strategy strategy, uint8_t *payload, uint32_t *plen, uint32_t avail_buflen) {
void *iph;
uint32_t iph_len;
struct udphdr *udph;
uint8_t *data;
uint32_t dlen;
int ret;

ret = udp_payload_split(payload, *plen,
&iph, &iph_len, &udph,
&data, &dlen);

uint32_t ipxv = netproto_version(payload, *plen);

if (ret < 0) {
return ret;
}


if (strategy.strategy == FAKE_STRAT_TTL) {
lgtrace_addp("set fake ttl to %d", strategy.faking_ttl);

if (ipxv == IP4VERSION) {
((struct iphdr *)iph)->ttl = strategy.faking_ttl;
} else if (ipxv == IP6VERSION) {
((struct ip6_hdr *)iph)->ip6_hops = strategy.faking_ttl;
} else {
lgerror(-EINVAL, "fail_packet: IP version is unsupported");
return -EINVAL;
}
}

if (ipxv == IP4VERSION) {
((struct iphdr *)iph)->frag_off = 0;
}


set_ip_checksum(iph, iph_len);

if (strategy.strategy == FAKE_STRAT_UDP_CHECK) {
lgtrace_addp("break fake tcp checksum");
udph->check += 1;
}

return 0;
}

int gen_fake_udp(struct udp_fake_type type,
const void *ipxh, uint32_t iph_len,
const struct udphdr *udph,
uint8_t *buf, uint32_t *buflen) {
uint32_t data_len = type.fake_len;
int ret;


if (!ipxh || !udph || !buf || !buflen)
return -EINVAL;

int ipxv = netproto_version(ipxh, iph_len);

if (ipxv == IP4VERSION) {
const struct iphdr *iph = ipxh;

memcpy(buf, iph, iph_len);
struct iphdr *niph = (struct iphdr *)buf;

niph->protocol = IPPROTO_UDP;
} else if (ipxv == IP6VERSION) {
const struct ip6_hdr *iph = ipxh;

iph_len = sizeof(struct ip6_hdr);
memcpy(buf, iph, iph_len);
struct ip6_hdr *niph = (struct ip6_hdr *)buf;

niph->ip6_nxt = IPPROTO_UDP;
} else {
return -EINVAL;
}

uint32_t dlen = iph_len + sizeof(struct udphdr) + data_len;

if (*buflen < dlen)
return -ENOMEM;

memcpy(buf + iph_len, udph, sizeof(struct udphdr));
uint8_t *bfdptr = buf + iph_len + sizeof(struct udphdr);

memset(bfdptr, 0, data_len);

if (ipxv == IP4VERSION) {
struct iphdr *niph = (struct iphdr *)buf;
niph->tot_len = htons(dlen);
niph->id = randint();
} else if (ipxv == IP6VERSION) {
struct ip6_hdr *niph = (struct ip6_hdr *)buf;
niph->ip6_plen = htons(dlen - iph_len);
}

struct udphdr *nudph = (struct udphdr *)(buf + iph_len);
nudph->len = htons(sizeof(struct udphdr) + data_len);


udp_fail_packet(type.strategy, buf, &dlen, *buflen);

*buflen = dlen;

return 0;
}
10 changes: 10 additions & 0 deletions quic.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef QUIC_H
#define QUIC_H
#include "types.h"
#include "utils.h"


/**
Expand Down Expand Up @@ -125,4 +126,13 @@ int quic_parse_initial_message(uint8_t *inpayload, uint32_t inplen,
struct quici_hdr *qhdr,
uint8_t **payload, uint32_t *plen);

// Like fail_packet for TCP
int udp_fail_packet(struct udp_failing_strategy strategy, uint8_t *payload, uint32_t *plen, uint32_t avail_buflen);

// Like gen_fake_sni for TCP
int gen_fake_udp(struct udp_fake_type type,
const void *ipxh, uint32_t iph_len,
const struct udphdr *udph,
uint8_t *buf, uint32_t *buflen);

#endif /* QUIC_H */
14 changes: 14 additions & 0 deletions utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,20 @@ struct fake_type {
struct failing_strategy strategy;
};

struct udp_failing_strategy {
unsigned int strategy;
uint8_t faking_ttl;
};

struct udp_fake_type {
uint16_t fake_len;

// faking strategy of the fake packet.
// Does not support bitmask, pass standalone strategy.
// Pass 0 if you don't want any faking procedures.
struct udp_failing_strategy strategy;
};

/**
* Invalidates the raw packet. The function aims to invalid the packet
* in such way as it will be accepted by DPI, but dropped by target server
Expand Down

0 comments on commit b2ac2e0

Please sign in to comment.