Update internal APIs, defaults

This commit is contained in:
Vadim Vetrov 2024-08-12 00:23:08 +03:00
parent e39bc9b059
commit 86bada6ea7
No known key found for this signature in database
GPG Key ID: E8A308689D7A73A5
3 changed files with 196 additions and 141 deletions

2
args.c
View File

@ -11,7 +11,7 @@
struct config_t config = { struct config_t config = {
.threads = THREADS_NUM, .threads = THREADS_NUM,
.frag_sni_reverse = 0, .frag_sni_reverse = 1,
.frag_sni_faked = 0, .frag_sni_faked = 0,
.fragmentation_strategy = FRAGMENTATION_STRATEGY, .fragmentation_strategy = FRAGMENTATION_STRATEGY,
.faking_strategy = FAKING_STRATEGY, .faking_strategy = FAKING_STRATEGY,

310
mangle.c
View File

@ -22,12 +22,131 @@ typedef uint16_t __u16;
#define lgerror(msg, ret) __extension__ ({errno = -ret; perror(msg);}) #define lgerror(msg, ret) __extension__ ({errno = -ret; perror(msg);})
#endif #endif
static int send_ip4_frags(const uint8_t *packet, uint32_t pktlen, const uint32_t *poses, uint32_t poses_sz, uint32_t dvs) {
if (poses_sz == 0) { int process_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
return instance_config.send_raw_packet(packet, pktlen); if (raw_payload_len > MAX_PACKET_SIZE) {
return PKT_ACCEPT;
} }
{ const struct iphdr *iph;
uint32_t iph_len;
const struct tcphdr *tcph;
uint32_t tcph_len;
const uint8_t *data;
uint32_t dlen;
int ret = tcp4_payload_split((uint8_t *)raw_payload, raw_payload_len,
(struct iphdr **)&iph, &iph_len, (struct tcphdr **)&tcph, &tcph_len,
(uint8_t **)&data, &dlen);
if (ret < 0) {
goto accept;
}
struct tls_verdict vrd = analyze_tls_data(data, dlen);
if (vrd.target_sni) {
if (config.verbose)
printf("Target SNI detected: %.*s\n", vrd.sni_len, data + vrd.sni_offset);
uint8_t payload[MAX_PACKET_SIZE];
uint32_t payload_len = raw_payload_len;
memcpy(payload, raw_payload, raw_payload_len);
struct iphdr *iph;
uint32_t iph_len;
struct tcphdr *tcph;
uint32_t tcph_len;
uint8_t *data;
uint32_t dlen;
int ret = tcp4_payload_split(payload, payload_len,
&iph, &iph_len, &tcph, &tcph_len,
&data, &dlen);
ip4_set_checksum(iph);
tcp4_set_checksum(tcph, iph);
if (dlen > 1480 && config.verbose) {
printf("WARNING! Client Hello packet is too big and may cause issues!\n");
}
if (config.fake_sni) {
post_fake_sni(iph, iph_len, tcph, tcph_len,
config.fake_sni_seq_len);
}
size_t ipd_offset;
size_t mid_offset;
switch (config.fragmentation_strategy) {
case FRAG_STRAT_TCP: {
ipd_offset = vrd.sni_offset;
mid_offset = ipd_offset + vrd.sni_len / 2;
uint32_t poses[] = { 2, mid_offset };
ret = send_tcp4_frags(payload, payload_len, poses, 2, 0);
if (ret < 0) {
lgerror("tcp4 send frags", ret);
goto accept;
}
goto drop;
}
break;
case FRAG_STRAT_IP: {
ipd_offset = ((char *)data - (char *)tcph) + vrd.sni_offset;
mid_offset = ipd_offset + vrd.sni_len / 2;
mid_offset += 8 - mid_offset % 8;
uint32_t poses[] = { mid_offset };
ret = send_ip4_frags(payload, payload_len, poses, 1, 0);
if (ret < 0) {
lgerror("ip4 send frags", ret);
goto accept;
}
goto drop;
}
break;
default:
ret = instance_config.send_raw_packet(payload, payload_len);
if (ret < 0) {
lgerror("raw pack send", ret);
goto accept;
}
goto drop;
}
goto drop;
}
accept:
return PKT_ACCEPT;
drop:
return PKT_DROP;
}
int send_ip4_frags(const uint8_t *packet, uint32_t pktlen, const uint32_t *poses, uint32_t poses_sz, uint32_t dvs) {
if (poses_sz == 0) {
if (config.seg2_delay && ((dvs > 0) ^ config.frag_sni_reverse)) {
if (!instance_config.send_delayed_packet) {
return -EINVAL;
}
instance_config.send_delayed_packet(
packet, pktlen, config.seg2_delay);
return 0;
} else {
return instance_config.send_raw_packet(
packet, pktlen);
}
} else {
uint8_t frag1[MAX_PACKET_SIZE]; uint8_t frag1[MAX_PACKET_SIZE];
uint8_t frag2[MAX_PACKET_SIZE]; uint8_t frag2[MAX_PACKET_SIZE];
uint32_t f1len = MAX_PACKET_SIZE; uint32_t f1len = MAX_PACKET_SIZE;
@ -49,22 +168,33 @@ static int send_ip4_frags(const uint8_t *packet, uint32_t pktlen, const uint32_t
return ret; return ret;
} }
dvs += poses[0]; if (config.frag_sni_reverse)
goto send_frag2;
send_frag1:
ret = send_ip4_frags(frag1, f1len, NULL, 0, 0); ret = send_ip4_frags(frag1, f1len, NULL, 0, 0);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
if (config.frag_sni_reverse)
goto out;
send_frag2:
dvs += poses[0];
ret = send_ip4_frags(frag2, f2len, poses + 1, poses_sz - 1, dvs); ret = send_ip4_frags(frag2, f2len, poses + 1, poses_sz - 1, dvs);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
if (config.frag_sni_reverse)
goto send_frag1;
} }
out:
return 0; return 0;
} }
static int send_tcp4_frags(const uint8_t *packet, uint32_t pktlen, const uint32_t *poses, uint32_t poses_sz, uint32_t dvs) { int send_tcp4_frags(const uint8_t *packet, uint32_t pktlen, const uint32_t *poses, uint32_t poses_sz, uint32_t dvs) {
if (poses_sz == 0) { if (poses_sz == 0) {
if (config.seg2_delay && ((dvs > 0) ^ config.frag_sni_reverse)) { if (config.seg2_delay && ((dvs > 0) ^ config.frag_sni_reverse)) {
if (!instance_config.send_delayed_packet) { if (!instance_config.send_delayed_packet) {
@ -157,154 +287,54 @@ out:
return 0; return 0;
} }
int post_fake_sni(const struct iphdr *iph, unsigned int iph_len,
const struct tcphdr *tcph, unsigned int tcph_len,
unsigned char sequence_len) {
uint8_t rfsiph[60];
uint8_t rfstcph[60];
int ret;
memcpy(rfsiph, iph, iph_len);
memcpy(rfstcph, tcph, tcph_len);
int process_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) { struct iphdr *fsiph = (void *)rfsiph;
if (raw_payload_len > MAX_PACKET_SIZE) { struct tcphdr *fstcph = (void *)rfstcph;
return PKT_ACCEPT;
}
const struct iphdr *iph; for (int i = 0; i < sequence_len; i++) {
uint32_t iph_len; uint8_t fake_sni[MAX_PACKET_SIZE];
const struct tcphdr *tcph; uint32_t fsn_len = MAX_PACKET_SIZE;
uint32_t tcph_len; ret = gen_fake_sni(fsiph, fstcph, fake_sni, &fsn_len);
const uint8_t *data; if (ret < 0) {
uint32_t dlen; lgerror("gen_fake_sni", ret);
return ret;
}
int ret = tcp4_payload_split((uint8_t *)raw_payload, raw_payload_len, ret = instance_config.send_raw_packet(fake_sni, fsn_len);
(struct iphdr **)&iph, &iph_len, (struct tcphdr **)&tcph, &tcph_len, if (ret < 0) {
(uint8_t **)&data, &dlen); lgerror("send fake sni", ret);
return ret;
}
if (ret < 0) {
goto accept;
}
struct tls_verdict vrd = analyze_tls_data(data, dlen);
if (vrd.target_sni) {
if (config.verbose)
printf("Target SNI detected: %.*s\n", vrd.sni_len, data + vrd.sni_offset);
uint8_t payload[MAX_PACKET_SIZE];
uint32_t payload_len = raw_payload_len;
memcpy(payload, raw_payload, raw_payload_len);
struct iphdr *iph;
uint32_t iph_len; uint32_t iph_len;
struct tcphdr *tcph;
uint32_t tcph_len; uint32_t tcph_len;
uint8_t *data; uint32_t plen;
uint32_t dlen; tcp4_payload_split(
fake_sni, fsn_len,
int ret = tcp4_payload_split(payload, payload_len, &fsiph, &iph_len, &fstcph, &tcph_len,
&iph, &iph_len, &tcph, &tcph_len, NULL, &plen);
&data, &dlen);
ip4_set_checksum(iph);
tcp4_set_checksum(tcph, iph);
if (dlen > 1480 && config.verbose) { fstcph->seq = htonl(ntohl(fstcph->seq) + plen);
printf("WARNING! Client Hello packet is too big and may cause issues!\n"); memcpy(rfsiph, fsiph, iph_len);
} memcpy(rfstcph, fstcph, tcph_len);
fsiph = (void *)rfsiph;
fstcph = (void *)rfstcph;
if (config.fake_sni) {
uint8_t rfsiph[60];
uint8_t rfstcph[60];
memcpy(rfsiph, iph, iph_len);
memcpy(rfstcph, tcph, tcph_len);
struct iphdr *fsiph = (void *)rfsiph;
struct tcphdr *fstcph = (void *)rfstcph;
for (int i = 0; i < config.fake_sni_seq_len; i++) {
uint8_t fake_sni[MAX_PACKET_SIZE];
uint32_t fsn_len = MAX_PACKET_SIZE;
ret = gen_fake_sni(fsiph, fstcph, fake_sni, &fsn_len);
if (ret < 0) {
lgerror("gen_fake_sni", ret);
goto accept;
}
ret = instance_config.send_raw_packet(fake_sni, fsn_len);
if (ret < 0) {
lgerror("send fake sni", ret);
goto accept;
}
uint32_t iph_len;
uint32_t tcph_len;
uint32_t plen;
tcp4_payload_split(fake_sni, fsn_len, &fsiph, &iph_len, &fstcph, &tcph_len, NULL, &plen);
fstcph->seq = htonl(ntohl(fstcph->seq) + plen);
memcpy(rfsiph, fsiph, iph_len);
memcpy(rfstcph, fstcph, tcph_len);
fsiph = (void *)rfsiph;
fstcph = (void *)rfstcph;
}
}
size_t ipd_offset;
size_t mid_offset;
switch (config.fragmentation_strategy) {
case FRAG_STRAT_TCP: {
ipd_offset = vrd.sni_offset;
mid_offset = ipd_offset + vrd.sni_len / 2;
uint32_t poses[] = { 2, mid_offset };
ret = send_tcp4_frags(payload, payload_len, poses, 2, 0);
if (ret < 0) {
lgerror("tcp4 send frags", ret);
goto accept;
}
goto drop;
}
break;
case FRAG_STRAT_IP: {
ipd_offset = ((char *)data - (char *)tcph) + vrd.sni_offset;
mid_offset = ipd_offset + vrd.sni_len / 2;
mid_offset += 8 - mid_offset % 8;
uint32_t poses[] = { mid_offset };
ret = send_tcp4_frags(payload, payload_len, poses, 1, 0);
if (ret < 0) {
lgerror("ip4 send frags", ret);
goto accept;
}
goto drop;
}
break;
default:
ret = instance_config.send_raw_packet(payload, payload_len);
if (ret < 0) {
lgerror("raw pack send", ret);
goto accept;
}
goto drop;
}
goto drop;
} }
accept: return 0;
return PKT_ACCEPT;
drop:
return PKT_DROP;
} }
void tcp4_set_checksum(struct tcphdr *tcph, struct iphdr *iph) void tcp4_set_checksum(struct tcphdr *tcph, struct iphdr *iph)
{ {
#ifdef KERNEL_SPACE #ifdef KERNEL_SPACE

View File

@ -103,4 +103,29 @@ int fail4_packet(uint8_t *payload, uint32_t plen);
* This is the primary function that traverses the packet. * This is the primary function that traverses the packet.
*/ */
int process_packet(const uint8_t *packet, uint32_t packet_len); int process_packet(const uint8_t *packet, uint32_t packet_len);
/**
* Sends fake client hello.
*/
int post_fake_sni(const struct iphdr *iph, unsigned int iph_len,
const struct tcphdr *tcph, unsigned int tcph_len,
unsigned char sequence_len);
/**
* Splits packet by poses and posts.
* Poses are relative to start of TCP payload.
* dvs used internally and should be zero.
*/
int send_tcp4_frags(
const uint8_t *packet, uint32_t pktlen,
const uint32_t *poses, uint32_t poses_len, uint32_t dvs);
/**
* Splits packet by poses and posts.
* Poses are relative to start of TCP payload.
* dvs used internally and should be zero.
*/
int send_ip4_frags(
const uint8_t *packet, uint32_t pktlen,
const uint32_t *poses, uint32_t poses_len, uint32_t dvs);
#endif /* YU_MANGLE_H */ #endif /* YU_MANGLE_H */