mirror of
https://github.com/Waujito/youtubeUnblock.git
synced 2024-12-22 22:36:03 +00:00
Support for ipv6
This commit is contained in:
parent
e8d86b9df6
commit
d530dd26d1
@ -20,9 +20,10 @@
|
|||||||
})
|
})
|
||||||
#endif /* PROGRAM_SPACE */
|
#endif /* PROGRAM_SPACE */
|
||||||
|
|
||||||
|
#define lgdebug(msg, ...) \
|
||||||
|
(LOG_LEVEL >= VERBOSE_DEBUG ? printf(msg, ##__VA_ARGS__) : 0)
|
||||||
|
|
||||||
#define lgdebugmsg(msg, ...) \
|
#define lgdebugmsg(msg, ...) lgdebug(msg "\n", ##__VA_ARGS__)
|
||||||
(LOG_LEVEL >= VERBOSE_DEBUG ? printf(msg "\n", ##__VA_ARGS__) : 0)
|
|
||||||
|
|
||||||
#define lgtracemsg(msg, ...) \
|
#define lgtracemsg(msg, ...) \
|
||||||
(LOG_LEVEL >= VERBOSE_TRACE ? printf(msg "\n", ##__VA_ARGS__) : 0)
|
(LOG_LEVEL >= VERBOSE_TRACE ? printf(msg "\n", ##__VA_ARGS__) : 0)
|
||||||
|
175
mangle.c
175
mangle.c
@ -16,23 +16,44 @@ int process_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const struct iphdr *iph;
|
const struct iphdr *iph;
|
||||||
|
const struct ip6_hdr *ip6h;
|
||||||
uint32_t iph_len;
|
uint32_t iph_len;
|
||||||
const uint8_t *ip_payload;
|
const uint8_t *ip_payload;
|
||||||
uint32_t ip_payload_len;
|
uint32_t ip_payload_len;
|
||||||
|
|
||||||
|
int transport_proto = -1;
|
||||||
|
int ipver = netproto_version(raw_payload, raw_payload_len);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (ipver == IP4VERSION) {
|
||||||
ret = ip4_payload_split((uint8_t *)raw_payload, raw_payload_len,
|
ret = ip4_payload_split((uint8_t *)raw_payload, raw_payload_len,
|
||||||
(struct iphdr **)&iph, &iph_len,
|
(struct iphdr **)&iph, &iph_len,
|
||||||
(uint8_t **)&ip_payload, &ip_payload_len);
|
(uint8_t **)&ip_payload, &ip_payload_len);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
goto accept;
|
||||||
|
|
||||||
|
transport_proto = iph ->protocol;
|
||||||
|
|
||||||
|
} else if (ipver == IP6VERSION) {
|
||||||
|
ret = ip6_payload_split((uint8_t *)raw_payload, raw_payload_len,
|
||||||
|
(struct ip6_hdr **)&ip6h, &iph_len,
|
||||||
|
(uint8_t **)&ip_payload, &ip_payload_len);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
goto accept;
|
||||||
|
|
||||||
|
transport_proto = ip6h->ip6_ctlun.ip6_un1.ip6_un1_nxt;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto accept;
|
goto accept;
|
||||||
|
|
||||||
switch (iph->protocol) {
|
switch (transport_proto) {
|
||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
return process_tcp4_packet(raw_payload, raw_payload_len);
|
return process_tcp_packet(raw_payload, raw_payload_len);
|
||||||
case IPPROTO_UDP:
|
case IPPROTO_UDP:
|
||||||
return process_udp4_packet(raw_payload, raw_payload_len);
|
return process_udp4_packet(raw_payload, raw_payload_len);
|
||||||
default:
|
default:
|
||||||
@ -45,18 +66,23 @@ drop:
|
|||||||
return PKT_DROP;
|
return PKT_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
int process_tcp4_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
|
int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
|
||||||
const struct iphdr *iph;
|
|
||||||
uint32_t iph_len;
|
|
||||||
const struct tcphdr *tcph;
|
const struct tcphdr *tcph;
|
||||||
uint32_t tcph_len;
|
uint32_t tcph_len;
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
uint32_t dlen;
|
uint32_t dlen;
|
||||||
|
|
||||||
int ret = tcp4_payload_split((uint8_t *)raw_payload, raw_payload_len,
|
int ipxv = netproto_version(raw_payload, raw_payload_len);
|
||||||
(struct iphdr **)&iph, &iph_len, (struct tcphdr **)&tcph, &tcph_len,
|
|
||||||
|
lgtrace_start("TCP");
|
||||||
|
lgtrace_addp("IPv%d", ipxv);
|
||||||
|
|
||||||
|
int ret = tcp_payload_split((uint8_t *)raw_payload, raw_payload_len,
|
||||||
|
NULL, NULL,
|
||||||
|
(struct tcphdr **)&tcph, &tcph_len,
|
||||||
(uint8_t **)&data, &dlen);
|
(uint8_t **)&data, &dlen);
|
||||||
|
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto accept;
|
goto accept;
|
||||||
}
|
}
|
||||||
@ -70,24 +96,28 @@ int process_tcp4_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
|
|||||||
uint32_t payload_len = raw_payload_len;
|
uint32_t payload_len = raw_payload_len;
|
||||||
memcpy(payload, raw_payload, raw_payload_len);
|
memcpy(payload, raw_payload, raw_payload_len);
|
||||||
|
|
||||||
struct iphdr *iph;
|
void *iph;
|
||||||
uint32_t iph_len;
|
uint32_t iph_len;
|
||||||
struct tcphdr *tcph;
|
struct tcphdr *tcph;
|
||||||
uint32_t tcph_len;
|
uint32_t tcph_len;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
uint32_t dlen;
|
uint32_t dlen;
|
||||||
|
|
||||||
int ret = tcp4_payload_split(payload, payload_len,
|
int ret = tcp_payload_split(payload, payload_len,
|
||||||
&iph, &iph_len, &tcph, &tcph_len,
|
&iph, &iph_len, &tcph, &tcph_len,
|
||||||
&data, &dlen);
|
&data, &dlen);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
lgerror("tcp_payload_split in targ_sni", ret);
|
||||||
|
goto accept;
|
||||||
|
}
|
||||||
|
|
||||||
if (config.fk_winsize) {
|
if (config.fk_winsize) {
|
||||||
tcph->window = htons(config.fk_winsize);
|
tcph->window = htons(config.fk_winsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
ip4_set_checksum(iph);
|
set_ip_checksum(iph, iph_len);
|
||||||
tcp4_set_checksum(tcph, iph);
|
set_tcp_checksum(tcph, iph, iph_len);
|
||||||
|
|
||||||
|
|
||||||
if (dlen > 1480 && config.verbose) {
|
if (dlen > 1480 && config.verbose) {
|
||||||
lgdebugmsg("WARNING! Client Hello packet is too big and may cause issues!");
|
lgdebugmsg("WARNING! Client Hello packet is too big and may cause issues!");
|
||||||
@ -123,7 +153,7 @@ int process_tcp4_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
|
|||||||
poses[1] = tmp;
|
poses[1] = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = send_tcp4_frags(payload, payload_len, poses, cnt, 0);
|
ret = send_tcp_frags(payload, payload_len, poses, cnt, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
lgerror("tcp4 send frags", ret);
|
lgerror("tcp4 send frags", ret);
|
||||||
goto accept;
|
goto accept;
|
||||||
@ -132,7 +162,8 @@ int process_tcp4_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
|
|||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FRAG_STRAT_IP: {
|
case FRAG_STRAT_IP:
|
||||||
|
if (ipxv != IP4VERSION) {
|
||||||
ipd_offset = ((char *)data - (char *)tcph) + vrd.sni_offset;
|
ipd_offset = ((char *)data - (char *)tcph) + vrd.sni_offset;
|
||||||
mid_offset = ipd_offset + vrd.sni_len / 2;
|
mid_offset = ipd_offset + vrd.sni_len / 2;
|
||||||
mid_offset += 8 - mid_offset % 8;
|
mid_offset += 8 - mid_offset % 8;
|
||||||
@ -163,8 +194,10 @@ int process_tcp4_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
printf("WARNING: IP fragmentation is supported only for IPv4\n");
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ret = instance_config.send_raw_packet(payload, payload_len);
|
ret = instance_config.send_raw_packet(payload, payload_len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -181,8 +214,14 @@ int process_tcp4_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
accept:
|
accept:
|
||||||
|
lgtrace_addp("accept");
|
||||||
|
lgtrace_end();
|
||||||
|
|
||||||
return PKT_ACCEPT;
|
return PKT_ACCEPT;
|
||||||
drop:
|
drop:
|
||||||
|
lgtrace_addp("drop");
|
||||||
|
lgtrace_end();
|
||||||
|
|
||||||
return PKT_DROP;
|
return PKT_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,7 +360,7 @@ out:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_tcp4_frags(const uint8_t *packet, uint32_t pktlen, const uint32_t *poses, uint32_t poses_sz, uint32_t dvs) {
|
int send_tcp_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) {
|
||||||
@ -333,6 +372,7 @@ int send_tcp4_frags(const uint8_t *packet, uint32_t pktlen, const uint32_t *pose
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
lgtrace_addp("raw send packet of %d bytes with %d dvs", pktlen, dvs);
|
||||||
return instance_config.send_raw_packet(
|
return instance_config.send_raw_packet(
|
||||||
packet, pktlen);
|
packet, pktlen);
|
||||||
}
|
}
|
||||||
@ -350,20 +390,24 @@ int send_tcp4_frags(const uint8_t *packet, uint32_t pktlen, const uint32_t *pose
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = tcp4_frag(packet, pktlen, poses[0] - dvs,
|
|
||||||
|
ret = tcp_frag(packet, pktlen, poses[0] - dvs,
|
||||||
frag1, &f1len, frag2, &f2len);
|
frag1, &f1len, frag2, &f2len);
|
||||||
|
|
||||||
|
lgtrace_addp("Packet split in %d bytes position of payload start, dvs: %d to two packets of %d and %d lengths", poses[0], dvs, f1len, f2len);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
lgerror("send_frags: frag: with context packet with size %d, position: %d, recursive dvs: %d", ret, pktlen, poses[0], dvs);
|
lgerror("send_frags: tcp_frag: with context packet with size %d, position: %d, recursive dvs: %d", ret, pktlen, poses[0], dvs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (config.frag_sni_reverse)
|
if (config.frag_sni_reverse)
|
||||||
goto send_frag2;
|
goto send_frag2;
|
||||||
|
|
||||||
send_frag1:
|
send_frag1:
|
||||||
{
|
{
|
||||||
ret = send_tcp4_frags(frag1, f1len, NULL, 0, 0);
|
ret = send_tcp_frags(frag1, f1len, NULL, 0, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -373,21 +417,22 @@ send_frag1:
|
|||||||
}
|
}
|
||||||
|
|
||||||
send_fake:
|
send_fake:
|
||||||
|
// TODO
|
||||||
if (config.frag_sni_faked) {
|
if (config.frag_sni_faked) {
|
||||||
uint32_t iphfl, tcphfl;
|
uint32_t iphfl, tcphfl;
|
||||||
ret = tcp4_payload_split(frag2, f2len, NULL, &iphfl, NULL, &tcphfl, NULL, NULL);
|
ret = tcp_payload_split(frag2, f2len, NULL, &iphfl, NULL, &tcphfl, NULL, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
lgerror("Invalid frag2", ret);
|
lgerror("Invalid frag2", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
memcpy(fake_pad, frag2, iphfl + tcphfl);
|
memcpy(fake_pad, frag2, iphfl + tcphfl);
|
||||||
memset(fake_pad + iphfl + tcphfl, 0, f2len - iphfl - tcphfl);
|
memset(fake_pad + iphfl + tcphfl, 0, f2len - iphfl - tcphfl);
|
||||||
ret = fail4_packet(fake_pad, f2len);
|
ret = fail_packet(fake_pad, f2len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
lgerror("Failed to fail packet", ret);
|
lgerror("Failed to fail packet", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ret = send_tcp4_frags(fake_pad, f2len, NULL, 0, 0);
|
ret = send_tcp_frags(fake_pad, f2len, NULL, 0, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -400,7 +445,7 @@ send_fake:
|
|||||||
send_frag2:
|
send_frag2:
|
||||||
{
|
{
|
||||||
dvs += poses[0];
|
dvs += poses[0];
|
||||||
ret = send_tcp4_frags(frag2, f2len, poses + 1, poses_sz - 1, dvs);
|
ret = send_tcp_frags(frag2, f2len, poses + 1, poses_sz - 1, dvs);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -413,28 +458,30 @@ out:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int post_fake_sni(const struct iphdr *iph, unsigned int iph_len,
|
int post_fake_sni(const void *iph, unsigned int iph_len,
|
||||||
const struct tcphdr *tcph, unsigned int tcph_len,
|
const struct tcphdr *tcph, unsigned int tcph_len,
|
||||||
unsigned char sequence_len) {
|
unsigned char sequence_len) {
|
||||||
uint8_t rfsiph[60];
|
uint8_t rfsiph[128];
|
||||||
uint8_t rfstcph[60];
|
uint8_t rfstcph[60];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memcpy(rfsiph, iph, iph_len);
|
memcpy(rfsiph, iph, iph_len);
|
||||||
memcpy(rfstcph, tcph, tcph_len);
|
memcpy(rfstcph, tcph, tcph_len);
|
||||||
|
|
||||||
struct iphdr *fsiph = (void *)rfsiph;
|
void *fsiph = (void *)rfsiph;
|
||||||
struct tcphdr *fstcph = (void *)rfstcph;
|
struct tcphdr *fstcph = (void *)rfstcph;
|
||||||
|
|
||||||
for (int i = 0; i < sequence_len; i++) {
|
for (int i = 0; i < sequence_len; i++) {
|
||||||
uint8_t fake_sni[MAX_PACKET_SIZE];
|
uint8_t fake_sni[MAX_PACKET_SIZE];
|
||||||
uint32_t fsn_len = MAX_PACKET_SIZE;
|
uint32_t fsn_len = MAX_PACKET_SIZE;
|
||||||
ret = gen_fake_sni(fsiph, fstcph, fake_sni, &fsn_len);
|
ret = gen_fake_sni(fsiph, iph_len, fstcph, tcph_len,
|
||||||
|
fake_sni, &fsn_len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
lgerror("gen_fake_sni", ret);
|
lgerror("gen_fake_sni", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lgtrace_addp("post fake sni #%d", i + 1);
|
||||||
ret = instance_config.send_raw_packet(fake_sni, fsn_len);
|
ret = instance_config.send_raw_packet(fake_sni, fsn_len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
lgerror("send fake sni", ret);
|
lgerror("send fake sni", ret);
|
||||||
@ -444,9 +491,10 @@ int post_fake_sni(const struct iphdr *iph, unsigned int iph_len,
|
|||||||
uint32_t iph_len;
|
uint32_t iph_len;
|
||||||
uint32_t tcph_len;
|
uint32_t tcph_len;
|
||||||
uint32_t plen;
|
uint32_t plen;
|
||||||
tcp4_payload_split(
|
tcp_payload_split(
|
||||||
fake_sni, fsn_len,
|
fake_sni, fsn_len,
|
||||||
&fsiph, &iph_len, &fstcph, &tcph_len,
|
&fsiph, &iph_len,
|
||||||
|
&fstcph, &tcph_len,
|
||||||
NULL, &plen);
|
NULL, &plen);
|
||||||
|
|
||||||
|
|
||||||
@ -692,42 +740,64 @@ brute:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int gen_fake_sni(const void *ipxh, uint32_t iph_len,
|
||||||
int gen_fake_sni(const struct iphdr *iph, const struct tcphdr *tcph,
|
const struct tcphdr *tcph, uint32_t tcph_len,
|
||||||
uint8_t *buf, uint32_t *buflen) {
|
uint8_t *buf, uint32_t *buflen) {
|
||||||
|
|
||||||
if (!iph || !tcph || !buf || !buflen)
|
if (!ipxh || !tcph || !buf || !buflen)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
int ip_len = iph->ihl * 4;
|
int ipxv = netproto_version(ipxh, iph_len);
|
||||||
int tcph_len = tcph->doff * 4;
|
|
||||||
|
if (ipxv == IP4VERSION) {
|
||||||
|
const struct iphdr *iph = ipxh;
|
||||||
|
|
||||||
|
memcpy(buf, iph, iph_len);
|
||||||
|
struct iphdr *niph = (struct iphdr *)buf;
|
||||||
|
|
||||||
|
niph->protocol = IPPROTO_TCP;
|
||||||
|
} 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_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_TCP;
|
||||||
|
} else {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
const char *data = config.fake_sni_pkt;
|
const char *data = config.fake_sni_pkt;
|
||||||
size_t data_len = config.fake_sni_pkt_sz;
|
size_t data_len = config.fake_sni_pkt_sz;
|
||||||
|
|
||||||
size_t dlen = ip_len + tcph_len + data_len;
|
size_t dlen = iph_len + tcph_len + data_len;
|
||||||
|
|
||||||
if (*buflen < dlen)
|
if (*buflen < dlen)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
memcpy(buf, iph, ip_len);
|
memcpy(buf + iph_len, tcph, tcph_len);
|
||||||
memcpy(buf + ip_len, tcph, tcph_len);
|
memcpy(buf + iph_len + tcph_len, data, data_len);
|
||||||
memcpy(buf + ip_len + tcph_len, data, data_len);
|
|
||||||
|
|
||||||
|
struct tcphdr *ntcph = (struct tcphdr *)(buf + iph_len);
|
||||||
|
|
||||||
|
if (ipxv == IP4VERSION) {
|
||||||
struct iphdr *niph = (struct iphdr *)buf;
|
struct iphdr *niph = (struct iphdr *)buf;
|
||||||
struct tcphdr *ntcph = (struct tcphdr *)(buf + ip_len);
|
|
||||||
|
|
||||||
niph->protocol = IPPROTO_TCP;
|
|
||||||
niph->tot_len = htons(dlen);
|
niph->tot_len = htons(dlen);
|
||||||
|
} else if (ipxv == IP6VERSION) {
|
||||||
|
struct ip6_hdr *niph = (struct ip6_hdr *)buf;
|
||||||
|
niph->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(dlen - iph_len);
|
||||||
|
}
|
||||||
|
|
||||||
fail4_packet(buf, *buflen);
|
fail_packet(buf, *buflen);
|
||||||
|
|
||||||
*buflen = dlen;
|
*buflen = dlen;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fail4_packet(uint8_t *payload, uint32_t plen) {
|
int fail_packet(uint8_t *payload, uint32_t plen) {
|
||||||
struct iphdr *iph;
|
void *iph;
|
||||||
uint32_t iph_len;
|
uint32_t iph_len;
|
||||||
struct tcphdr *tcph;
|
struct tcphdr *tcph;
|
||||||
uint32_t tcph_len;
|
uint32_t tcph_len;
|
||||||
@ -735,7 +805,7 @@ int fail4_packet(uint8_t *payload, uint32_t plen) {
|
|||||||
uint32_t dlen;
|
uint32_t dlen;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = tcp4_payload_split(payload, plen,
|
ret = tcp_payload_split(payload, plen,
|
||||||
&iph, &iph_len, &tcph, &tcph_len,
|
&iph, &iph_len, &tcph, &tcph_len,
|
||||||
&data, &dlen);
|
&data, &dlen);
|
||||||
|
|
||||||
@ -743,6 +813,7 @@ int fail4_packet(uint8_t *payload, uint32_t plen) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (config.faking_strategy == FAKE_STRAT_RAND_SEQ) {
|
if (config.faking_strategy == FAKE_STRAT_RAND_SEQ) {
|
||||||
#ifdef KERNEL_SCOPE
|
#ifdef KERNEL_SCOPE
|
||||||
tcph->seq = 124;
|
tcph->seq = 124;
|
||||||
@ -754,11 +825,19 @@ int fail4_packet(uint8_t *payload, uint32_t plen) {
|
|||||||
} else if (config.faking_strategy == FAKE_STRAT_PAST_SEQ) {
|
} else if (config.faking_strategy == FAKE_STRAT_PAST_SEQ) {
|
||||||
tcph->seq = htonl(ntohl(tcph->seq) - dlen);
|
tcph->seq = htonl(ntohl(tcph->seq) - dlen);
|
||||||
} else if (config.faking_strategy == FAKE_STRAT_TTL) {
|
} else if (config.faking_strategy == FAKE_STRAT_TTL) {
|
||||||
iph->ttl = config.faking_ttl;
|
uint32_t ipxv = netproto_version(payload, plen);
|
||||||
|
if (ipxv == IP4VERSION) {
|
||||||
|
((struct iphdr *)iph)->ttl = config.faking_ttl;
|
||||||
|
} else if (ipxv == IP6VERSION) {
|
||||||
|
((struct ip6_hdr *)iph)->ip6_ctlun.ip6_un1.ip6_un1_hlim = config.faking_ttl;
|
||||||
|
} else {
|
||||||
|
lgerror("fail_packet: IP version is unsupported", -EINVAL);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ip4_set_checksum(iph);
|
set_ip_checksum(iph, iph_len);
|
||||||
tcp4_set_checksum(tcph, iph);
|
set_tcp_checksum(tcph, iph, iph_len);
|
||||||
|
|
||||||
if (config.faking_strategy == FAKE_STRAT_TCP_CHECK) {
|
if (config.faking_strategy == FAKE_STRAT_TCP_CHECK) {
|
||||||
tcph->check += 1;
|
tcph->check += 1;
|
||||||
|
11
mangle.h
11
mangle.h
@ -22,14 +22,15 @@ struct tls_verdict analyze_tls_data(const uint8_t *data, uint32_t dlen);
|
|||||||
/**
|
/**
|
||||||
* Generates fake client hello message
|
* Generates fake client hello message
|
||||||
*/
|
*/
|
||||||
int gen_fake_sni(const struct iphdr *iph, const struct tcphdr *tcph,
|
int gen_fake_sni(const void *iph, uint32_t iph_len,
|
||||||
|
const struct tcphdr *tcph, uint32_t tcph_len,
|
||||||
uint8_t *buf, uint32_t *buflen);
|
uint8_t *buf, uint32_t *buflen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalidates the raw packet. The function aims to invalid the packet
|
* 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
|
* in such way as it will be accepted by DPI, but dropped by target server
|
||||||
*/
|
*/
|
||||||
int fail4_packet(uint8_t *payload, uint32_t plen);
|
int fail_packet(uint8_t *payload, uint32_t plen);
|
||||||
|
|
||||||
#define PKT_ACCEPT 0
|
#define PKT_ACCEPT 0
|
||||||
#define PKT_DROP 1
|
#define PKT_DROP 1
|
||||||
@ -45,7 +46,7 @@ int process_packet(const uint8_t *packet, uint32_t packet_len);
|
|||||||
* Processe the TCP packet.
|
* Processe the TCP packet.
|
||||||
* Returns verdict.
|
* Returns verdict.
|
||||||
*/
|
*/
|
||||||
int process_tcp4_packet(const uint8_t *raw_payload, uint32_t raw_payload_len);
|
int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,7 +58,7 @@ int process_udp4_packet(const uint8_t *pkt, uint32_t pktlen);
|
|||||||
/**
|
/**
|
||||||
* Sends fake client hello.
|
* Sends fake client hello.
|
||||||
*/
|
*/
|
||||||
int post_fake_sni(const struct iphdr *iph, unsigned int iph_len,
|
int post_fake_sni(const void *iph, unsigned int iph_len,
|
||||||
const struct tcphdr *tcph, unsigned int tcph_len,
|
const struct tcphdr *tcph, unsigned int tcph_len,
|
||||||
unsigned char sequence_len);
|
unsigned char sequence_len);
|
||||||
|
|
||||||
@ -66,7 +67,7 @@ int post_fake_sni(const struct iphdr *iph, unsigned int iph_len,
|
|||||||
* Poses are relative to start of TCP payload.
|
* Poses are relative to start of TCP payload.
|
||||||
* dvs used internally and should be zero.
|
* dvs used internally and should be zero.
|
||||||
*/
|
*/
|
||||||
int send_tcp4_frags(
|
int send_tcp_frags(
|
||||||
const uint8_t *packet, uint32_t pktlen,
|
const uint8_t *packet, uint32_t pktlen,
|
||||||
const uint32_t *poses, uint32_t poses_len, uint32_t dvs);
|
const uint32_t *poses, uint32_t poses_len, uint32_t dvs);
|
||||||
|
|
||||||
|
1
types.h
1
types.h
@ -41,6 +41,7 @@ typedef __i64 int64_t;
|
|||||||
#define USER_SPACE
|
#define USER_SPACE
|
||||||
#include <arpa/inet.h> // IWYU pragma: export
|
#include <arpa/inet.h> // IWYU pragma: export
|
||||||
#include <netinet/ip.h> // IWYU pragma: export
|
#include <netinet/ip.h> // IWYU pragma: export
|
||||||
|
#include <netinet/ip6.h> // IWYU pragma: export
|
||||||
#include <netinet/tcp.h> // IWYU pragma: export
|
#include <netinet/tcp.h> // IWYU pragma: export
|
||||||
#include <netinet/udp.h> // IWYU pragma: export
|
#include <netinet/udp.h> // IWYU pragma: export
|
||||||
#endif
|
#endif
|
||||||
|
170
utils.c
170
utils.c
@ -1,11 +1,13 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#ifdef KERNEL_SPACE
|
#ifdef KERNEL_SPACE
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#else
|
#else
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
|
#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_ipv6.h>
|
||||||
#include <libnetfilter_queue/libnetfilter_queue_tcp.h>
|
#include <libnetfilter_queue/libnetfilter_queue_tcp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -34,6 +36,36 @@ void ip4_set_checksum(struct iphdr *iph)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tcp6_set_checksum(struct tcphdr *tcph, struct ip6_hdr *iph) {
|
||||||
|
uint16_t old_check = ntohs(tcph->check);
|
||||||
|
|
||||||
|
nfq_tcp_compute_checksum_ipv6(tcph, iph);
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_ip_checksum(void *iph, uint32_t iphb_len) {
|
||||||
|
int ipvx = netproto_version(iph, iphb_len);
|
||||||
|
|
||||||
|
if (ipvx == IP4VERSION) {
|
||||||
|
ip4_set_checksum(iph);
|
||||||
|
} else if (ipvx == IP6VERSION) { // IP6 has no checksums
|
||||||
|
} else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_tcp_checksum(struct tcphdr *tcph, void *iph, uint32_t iphb_len) {
|
||||||
|
int ipvx = netproto_version(iph, iphb_len);
|
||||||
|
|
||||||
|
if (ipvx == IP4VERSION) {
|
||||||
|
tcp4_set_checksum(tcph, iph);
|
||||||
|
} else if (ipvx == IP6VERSION) {
|
||||||
|
tcp6_set_checksum(tcph, iph);
|
||||||
|
} else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ip4_payload_split(uint8_t *pkt, uint32_t buflen,
|
int ip4_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||||
struct iphdr **iph, uint32_t *iph_len,
|
struct iphdr **iph, uint32_t *iph_len,
|
||||||
@ -44,7 +76,7 @@ int ip4_payload_split(uint8_t *pkt, uint32_t buflen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct iphdr *hdr = (struct iphdr *)pkt;
|
struct iphdr *hdr = (struct iphdr *)pkt;
|
||||||
if (hdr->version != IPVERSION) {
|
if (netproto_version(pkt, buflen) != IP4VERSION) {
|
||||||
lgerror("ip4_payload_split: ipversion", -EINVAL);
|
lgerror("ip4_payload_split: ipversion", -EINVAL);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -110,6 +142,97 @@ int tcp4_payload_split(uint8_t *pkt, uint32_t buflen,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ip6_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||||
|
struct ip6_hdr **iph, uint32_t *iph_len,
|
||||||
|
uint8_t **payload, uint32_t *plen) {
|
||||||
|
if (pkt == NULL || buflen < sizeof(struct ip6_hdr)) {
|
||||||
|
lgerror("ip6_payload_split: pkt|buflen", -EINVAL);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ip6_hdr *hdr = (struct ip6_hdr *)pkt;
|
||||||
|
if (netproto_version(pkt, buflen) != 6) {
|
||||||
|
lgerror("ip6_payload_split: ip6version", -EINVAL);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t hdr_len = sizeof(struct ip6_hdr);
|
||||||
|
uint32_t pktlen = ntohs(hdr->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||||
|
if (buflen < pktlen) {
|
||||||
|
lgerror("ip6_payload_split: buflen cmp pktlen: %d %d", -EINVAL, buflen, pktlen);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iph)
|
||||||
|
*iph = hdr;
|
||||||
|
if (iph_len)
|
||||||
|
*iph_len = hdr_len;
|
||||||
|
if (payload)
|
||||||
|
*payload = pkt + hdr_len;
|
||||||
|
if (plen)
|
||||||
|
*plen = pktlen;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcp6_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||||
|
struct ip6_hdr **iph, uint32_t *iph_len,
|
||||||
|
struct tcphdr **tcph, uint32_t *tcph_len,
|
||||||
|
uint8_t **payload, uint32_t *plen) {
|
||||||
|
struct ip6_hdr *hdr;
|
||||||
|
uint32_t hdr_len;
|
||||||
|
struct tcphdr *thdr;
|
||||||
|
uint32_t thdr_len;
|
||||||
|
|
||||||
|
uint8_t *tcph_pl;
|
||||||
|
uint32_t tcph_plen;
|
||||||
|
|
||||||
|
if (ip6_payload_split(pkt, buflen, &hdr, &hdr_len,
|
||||||
|
&tcph_pl, &tcph_plen)){
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (
|
||||||
|
hdr->ip6_ctlun.ip6_un1.ip6_un1_nxt != IPPROTO_TCP ||
|
||||||
|
tcph_plen < sizeof(struct tcphdr)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
thdr = (struct tcphdr *)(tcph_pl);
|
||||||
|
thdr_len = thdr->doff * 4;
|
||||||
|
|
||||||
|
if (thdr_len > tcph_plen) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iph) *iph = hdr;
|
||||||
|
if (iph_len) *iph_len = hdr_len;
|
||||||
|
if (tcph) *tcph = thdr;
|
||||||
|
if (tcph_len) *tcph_len = thdr_len;
|
||||||
|
if (payload) *payload = tcph_pl + thdr_len;
|
||||||
|
if (plen) *plen = tcph_plen - thdr_len;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcp_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||||
|
void **iph, uint32_t *iph_len,
|
||||||
|
struct tcphdr **tcph, uint32_t *tcph_len,
|
||||||
|
uint8_t **payload, uint32_t *plen) {
|
||||||
|
int netvers = netproto_version(pkt, buflen);
|
||||||
|
if (netvers == IP4VERSION) {
|
||||||
|
return tcp4_payload_split(pkt, buflen, (struct iphdr **)iph, iph_len, tcph, tcph_len, payload, plen);
|
||||||
|
} else if (netvers == IP6VERSION) {
|
||||||
|
return tcp6_payload_split(pkt, buflen, (struct ip6_hdr **)iph, iph_len, tcph, tcph_len, payload, plen);
|
||||||
|
} else {
|
||||||
|
lgerror("Internet Protocol version is unsupported", -EINVAL);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int udp4_payload_split(uint8_t *pkt, uint32_t buflen,
|
int udp4_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||||
struct iphdr **iph, uint32_t *iph_len,
|
struct iphdr **iph, uint32_t *iph_len,
|
||||||
struct udphdr **udph,
|
struct udphdr **udph,
|
||||||
@ -222,9 +345,6 @@ int ip4_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset,
|
|||||||
f2_hdr->frag_off = htons(f2_frag_off);
|
f2_hdr->frag_off = htons(f2_frag_off);
|
||||||
f2_hdr->tot_len = htons(f2_dlen);
|
f2_hdr->tot_len = htons(f2_dlen);
|
||||||
|
|
||||||
|
|
||||||
lgdebugmsg("Packet split in portion %u %u", f1_plen, f2_plen);
|
|
||||||
|
|
||||||
ip4_set_checksum(f1_hdr);
|
ip4_set_checksum(f1_hdr);
|
||||||
ip4_set_checksum(f2_hdr);
|
ip4_set_checksum(f2_hdr);
|
||||||
|
|
||||||
@ -232,11 +352,12 @@ int ip4_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// split packet to two tcp-on-ipv4 segments.
|
// split packet to two tcp-on-ipv4 segments.
|
||||||
int tcp4_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset,
|
int tcp_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset,
|
||||||
uint8_t *seg1, uint32_t *s1len,
|
uint8_t *seg1, uint32_t *s1len,
|
||||||
uint8_t *seg2, uint32_t *s2len) {
|
uint8_t *seg2, uint32_t *s2len) {
|
||||||
|
|
||||||
struct iphdr *hdr;
|
// struct ip6_hdr *hdr6;
|
||||||
|
void *hdr;
|
||||||
uint32_t hdr_len;
|
uint32_t hdr_len;
|
||||||
struct tcphdr *tcph;
|
struct tcphdr *tcph;
|
||||||
uint32_t tcph_len;
|
uint32_t tcph_len;
|
||||||
@ -247,24 +368,29 @@ int tcp4_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset,
|
|||||||
if (!seg1 || !s1len || !seg2 || !s2len)
|
if (!seg1 || !s1len || !seg2 || !s2len)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if ((ret = tcp4_payload_split((uint8_t *)pkt, buflen,
|
if ((ret = tcp_payload_split((uint8_t *)pkt, buflen,
|
||||||
&hdr, &hdr_len,
|
&hdr, &hdr_len,
|
||||||
&tcph, &tcph_len,
|
&tcph, &tcph_len,
|
||||||
(uint8_t **)&payload, &plen)) < 0) {
|
(uint8_t **)&payload, &plen)) < 0) {
|
||||||
lgerror("tcp4_frag: tcp4_payload_split", ret);
|
lgerror("tcp_frag: tcp_payload_split", ret);
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ipvx = netproto_version(pkt, buflen);
|
||||||
|
|
||||||
|
|
||||||
|
if (ipvx == IP4VERSION) {
|
||||||
|
struct iphdr *iphdr = hdr;
|
||||||
if (
|
if (
|
||||||
ntohs(hdr->frag_off) & IP_MF ||
|
ntohs(iphdr->frag_off) & IP_MF ||
|
||||||
ntohs(hdr->frag_off) & IP_OFFMASK) {
|
ntohs(iphdr->frag_off) & IP_OFFMASK) {
|
||||||
lgdebugmsg("tcp4_frag: frag value: %d",
|
lgdebugmsg("tcp_frag: ip4: frag value: %d",
|
||||||
ntohs(hdr->frag_off));
|
ntohs(iphdr->frag_off));
|
||||||
lgerror("tcp4_frag: ip fragmentation is set", -EINVAL);
|
lgerror("tcp_frag: ip4: ip fragmentation is set", -EINVAL);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (plen <= payload_offset) {
|
if (plen <= payload_offset) {
|
||||||
@ -292,21 +418,25 @@ int tcp4_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset,
|
|||||||
memcpy(seg1 + hdr_len + tcph_len, payload, s1_plen);
|
memcpy(seg1 + hdr_len + tcph_len, payload, s1_plen);
|
||||||
memcpy(seg2 + hdr_len + tcph_len, payload + payload_offset, s2_plen);
|
memcpy(seg2 + hdr_len + tcph_len, payload + payload_offset, s2_plen);
|
||||||
|
|
||||||
|
if (ipvx == IP4VERSION) {
|
||||||
struct iphdr *s1_hdr = (void *)seg1;
|
struct iphdr *s1_hdr = (void *)seg1;
|
||||||
struct iphdr *s2_hdr = (void *)seg2;
|
struct iphdr *s2_hdr = (void *)seg2;
|
||||||
|
s1_hdr->tot_len = htons(s1_dlen);
|
||||||
|
s2_hdr->tot_len = htons(s2_dlen);
|
||||||
|
} else {
|
||||||
|
struct ip6_hdr *s1_hdr = (void *)seg1;
|
||||||
|
struct ip6_hdr *s2_hdr = (void *)seg2;
|
||||||
|
s1_hdr->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(s1_dlen - hdr_len);
|
||||||
|
s2_hdr->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(s2_dlen - hdr_len);
|
||||||
|
}
|
||||||
|
|
||||||
struct tcphdr *s1_tcph = (void *)(seg1 + hdr_len);
|
struct tcphdr *s1_tcph = (void *)(seg1 + hdr_len);
|
||||||
struct tcphdr *s2_tcph = (void *)(seg2 + hdr_len);
|
struct tcphdr *s2_tcph = (void *)(seg2 + hdr_len);
|
||||||
|
|
||||||
s1_hdr->tot_len = htons(s1_dlen);
|
|
||||||
s2_hdr->tot_len = htons(s2_dlen);
|
|
||||||
|
|
||||||
s2_tcph->seq = htonl(ntohl(s2_tcph->seq) + payload_offset);
|
s2_tcph->seq = htonl(ntohl(s2_tcph->seq) + payload_offset);
|
||||||
|
|
||||||
lgdebugmsg("Packet split in portion %u %u", s1_plen, s2_plen);
|
set_tcp_checksum(s1_tcph, seg1, hdr_len);
|
||||||
|
set_tcp_checksum(s2_tcph, seg2, hdr_len);
|
||||||
tcp4_set_checksum(s1_tcph, s1_hdr);
|
|
||||||
tcp4_set_checksum(s2_tcph, s2_hdr);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
43
utils.h
43
utils.h
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
#define IP4VERSION 4
|
||||||
|
#define IP6VERSION 6
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits the packet to two IP fragments on position payload_offset.
|
* Splits the packet to two IP fragments on position payload_offset.
|
||||||
* payload_offset indicates the position relatively to start of IP payload
|
* payload_offset indicates the position relatively to start of IP payload
|
||||||
@ -17,11 +20,16 @@ int ip4_frag(const uint8_t *pkt, uint32_t pktlen,
|
|||||||
* Splits the packet to two TCP segments on position payload_offset
|
* Splits the packet to two TCP segments on position payload_offset
|
||||||
* payload_offset indicates the position relatively to start of TCP payload.
|
* payload_offset indicates the position relatively to start of TCP payload.
|
||||||
*/
|
*/
|
||||||
int tcp4_frag(const uint8_t *pkt, uint32_t pktlen,
|
// int tcp4_frag(const uint8_t *pkt, uint32_t pktlen,
|
||||||
|
// uint32_t payload_offset,
|
||||||
|
// uint8_t *seg1, uint32_t *s1len,
|
||||||
|
// uint8_t *seg2, uint32_t *s2len);
|
||||||
|
int tcp_frag(const uint8_t *pkt, uint32_t pktlen,
|
||||||
uint32_t payload_offset,
|
uint32_t payload_offset,
|
||||||
uint8_t *seg1, uint32_t *s1len,
|
uint8_t *seg1, uint32_t *s1len,
|
||||||
uint8_t *seg2, uint32_t *s2len);
|
uint8_t *seg2, uint32_t *s2len);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits the raw packet payload to ip header and ip payload.
|
* Splits the raw packet payload to ip header and ip payload.
|
||||||
*/
|
*/
|
||||||
@ -29,6 +37,14 @@ int ip4_payload_split(uint8_t *pkt, uint32_t buflen,
|
|||||||
struct iphdr **iph, uint32_t *iph_len,
|
struct iphdr **iph, uint32_t *iph_len,
|
||||||
uint8_t **payload, uint32_t *plen);
|
uint8_t **payload, uint32_t *plen);
|
||||||
|
|
||||||
|
static inline int netproto_version(const uint8_t *pkt, uint32_t buflen) {
|
||||||
|
if (pkt == NULL || buflen == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return (*pkt) >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits the raw packet payload to ip header, tcp header and tcp payload.
|
* Splits the raw packet payload to ip header, tcp header and tcp payload.
|
||||||
*/
|
*/
|
||||||
@ -37,6 +53,26 @@ int tcp4_payload_split(uint8_t *pkt, uint32_t buflen,
|
|||||||
struct tcphdr **tcph, uint32_t *tcph_len,
|
struct tcphdr **tcph, uint32_t *tcph_len,
|
||||||
uint8_t **payload, uint32_t *plen);
|
uint8_t **payload, uint32_t *plen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits the raw packet payload to ip header and ip payload.
|
||||||
|
*/
|
||||||
|
int ip6_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||||
|
struct ip6_hdr **iph, uint32_t *iph_len,
|
||||||
|
uint8_t **payload, uint32_t *plen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits the raw packet payload to ip header, tcp header and tcp payload.
|
||||||
|
*/
|
||||||
|
int tcp6_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||||
|
struct ip6_hdr **iph, uint32_t *iph_len,
|
||||||
|
struct tcphdr **tcph, uint32_t *tcph_len,
|
||||||
|
uint8_t **payload, uint32_t *plen);
|
||||||
|
|
||||||
|
int tcp_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||||
|
void **iph, uint32_t *iph_len,
|
||||||
|
struct tcphdr **tcph, uint32_t *tcph_len,
|
||||||
|
uint8_t **payload, uint32_t *plen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits the raw packet payload to ip header, udp header and udp payload.
|
* Splits the raw packet payload to ip header, udp header and udp payload.
|
||||||
*/
|
*/
|
||||||
@ -47,5 +83,10 @@ int udp4_payload_split(uint8_t *pkt, uint32_t buflen,
|
|||||||
|
|
||||||
void tcp4_set_checksum(struct tcphdr *tcph, struct iphdr *iph);
|
void tcp4_set_checksum(struct tcphdr *tcph, struct iphdr *iph);
|
||||||
void ip4_set_checksum(struct iphdr *iph);
|
void ip4_set_checksum(struct iphdr *iph);
|
||||||
|
void ip6_set_checksum(struct ip6_hdr *iph);
|
||||||
|
void tcp6_set_checksum(struct tcphdr *tcph, struct ip6_hdr *iph);
|
||||||
|
|
||||||
|
int set_ip_checksum(void *iph, uint32_t iphb_len);
|
||||||
|
int set_tcp_checksum(struct tcphdr *tcph, void *iph, uint32_t iphb_len);
|
||||||
|
|
||||||
#endif /* UTILS_H */
|
#endif /* UTILS_H */
|
||||||
|
182
youtubeUnblock.c
182
youtubeUnblock.c
@ -37,6 +37,9 @@
|
|||||||
pthread_mutex_t rawsocket_lock;
|
pthread_mutex_t rawsocket_lock;
|
||||||
int rawsocket = -2;
|
int rawsocket = -2;
|
||||||
|
|
||||||
|
pthread_mutex_t raw6socket_lock;
|
||||||
|
int raw6socket = -2;
|
||||||
|
|
||||||
static int open_socket(struct mnl_socket **_nl) {
|
static int open_socket(struct mnl_socket **_nl) {
|
||||||
struct mnl_socket *nl = NULL;
|
struct mnl_socket *nl = NULL;
|
||||||
nl = mnl_socket_open(NETLINK_NETFILTER);
|
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||||
@ -123,6 +126,134 @@ static int close_raw_socket(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int open_raw6_socket(void) {
|
||||||
|
if (raw6socket != -2) {
|
||||||
|
errno = EALREADY;
|
||||||
|
perror("Raw socket is already opened");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
raw6socket = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
|
||||||
|
if (rawsocket == -1) {
|
||||||
|
perror("Unable to create raw socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mark = RAWSOCKET_MARK;
|
||||||
|
if (setsockopt(raw6socket, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "setsockopt(SO_MARK, %d) failed\n", mark);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mst = pthread_mutex_init(&raw6socket_lock, NULL);
|
||||||
|
if (mst) {
|
||||||
|
fprintf(stderr, "Mutex err: %d\n", mst);
|
||||||
|
close(raw6socket);
|
||||||
|
errno = mst;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return raw6socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int close_raw6_socket(void) {
|
||||||
|
if (raw6socket < 0) {
|
||||||
|
errno = EALREADY;
|
||||||
|
perror("Raw socket is not set");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close(raw6socket)) {
|
||||||
|
perror("Unable to close raw socket");
|
||||||
|
pthread_mutex_destroy(&rawsocket_lock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&raw6socket_lock);
|
||||||
|
|
||||||
|
raw6socket = -2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_raw_ipv4(const uint8_t *pkt, uint32_t pktlen) {
|
||||||
|
int ret;
|
||||||
|
if (pktlen > AVAILABLE_MTU) return -ENOMEM;
|
||||||
|
|
||||||
|
struct iphdr *iph;
|
||||||
|
|
||||||
|
if ((ret = ip4_payload_split(
|
||||||
|
(uint8_t *)pkt, pktlen, &iph, NULL, NULL, NULL)) < 0) {
|
||||||
|
errno = -ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in daddr = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
/* Always 0 for raw socket */
|
||||||
|
.sin_port = 0,
|
||||||
|
.sin_addr = {
|
||||||
|
.s_addr = iph->daddr
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (config.threads != 1)
|
||||||
|
pthread_mutex_lock(&rawsocket_lock);
|
||||||
|
|
||||||
|
int sent = sendto(rawsocket,
|
||||||
|
pkt, pktlen, 0,
|
||||||
|
(struct sockaddr *)&daddr, sizeof(daddr));
|
||||||
|
|
||||||
|
if (config.threads != 1)
|
||||||
|
pthread_mutex_unlock(&rawsocket_lock);
|
||||||
|
|
||||||
|
/* The function will return -errno on error as well as errno value set itself */
|
||||||
|
if (sent < 0) sent = -errno;
|
||||||
|
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_raw_ipv6(const uint8_t *pkt, uint32_t pktlen) {
|
||||||
|
int ret;
|
||||||
|
if (pktlen > AVAILABLE_MTU) return -ENOMEM;
|
||||||
|
|
||||||
|
struct ip6_hdr *iph;
|
||||||
|
|
||||||
|
if ((ret = ip6_payload_split(
|
||||||
|
(uint8_t *)pkt, pktlen, &iph, NULL, NULL, NULL)) < 0) {
|
||||||
|
errno = -ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in6 daddr = {
|
||||||
|
.sin6_family = AF_INET6,
|
||||||
|
/* Always 0 for raw socket */
|
||||||
|
.sin6_port = 0,
|
||||||
|
.sin6_addr = iph->ip6_dst
|
||||||
|
};
|
||||||
|
|
||||||
|
tcp6_set_checksum((void *)(uint8_t *)pkt + sizeof(struct ip6_hdr), (void *)pkt);
|
||||||
|
|
||||||
|
|
||||||
|
if (config.threads != 1)
|
||||||
|
pthread_mutex_lock(&rawsocket_lock);
|
||||||
|
|
||||||
|
int sent = sendto(raw6socket,
|
||||||
|
pkt, pktlen, 0,
|
||||||
|
(struct sockaddr *)&daddr, sizeof(daddr));
|
||||||
|
|
||||||
|
lgtrace_addp("rawsocket sent %d", sent);
|
||||||
|
|
||||||
|
if (config.threads != 1)
|
||||||
|
pthread_mutex_unlock(&rawsocket_lock);
|
||||||
|
|
||||||
|
/* The function will return -errno on error as well as errno value set itself */
|
||||||
|
if (sent < 0) sent = -errno;
|
||||||
|
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
|
||||||
static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) {
|
static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) {
|
||||||
int ret;
|
int ret;
|
||||||
@ -138,7 +269,7 @@ static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) {
|
|||||||
|
|
||||||
switch (config.fragmentation_strategy) {
|
switch (config.fragmentation_strategy) {
|
||||||
case FRAG_STRAT_TCP:
|
case FRAG_STRAT_TCP:
|
||||||
if ((ret = tcp4_frag(pkt, pktlen, AVAILABLE_MTU-128,
|
if ((ret = tcp_frag(pkt, pktlen, AVAILABLE_MTU-128,
|
||||||
buff1, &buff1_size, buff2, &buff2_size)) < 0) {
|
buff1, &buff1_size, buff2, &buff2_size)) < 0) {
|
||||||
|
|
||||||
errno = -ret;
|
errno = -ret;
|
||||||
@ -176,38 +307,15 @@ static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) {
|
|||||||
return sent;
|
return sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ipvx = netproto_version(pkt, pktlen);
|
||||||
|
|
||||||
struct iphdr *iph;
|
if (ipvx == IP4VERSION)
|
||||||
|
return send_raw_ipv4(pkt, pktlen);
|
||||||
|
else if (ipvx == IP6VERSION)
|
||||||
|
return send_raw_ipv6(pkt, pktlen);
|
||||||
|
|
||||||
if ((ret = ip4_payload_split(
|
printf("proto version %d is unsupported\n", ipvx);
|
||||||
(uint8_t *)pkt, pktlen, &iph, NULL, NULL, NULL)) < 0) {
|
return -EINVAL;
|
||||||
errno = -ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in daddr = {
|
|
||||||
.sin_family = AF_INET,
|
|
||||||
/* Always 0 for raw socket */
|
|
||||||
.sin_port = 0,
|
|
||||||
.sin_addr = {
|
|
||||||
.s_addr = iph->daddr
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (config.threads != 1)
|
|
||||||
pthread_mutex_lock(&rawsocket_lock);
|
|
||||||
|
|
||||||
int sent = sendto(rawsocket,
|
|
||||||
pkt, pktlen, 0,
|
|
||||||
(struct sockaddr *)&daddr, sizeof(daddr));
|
|
||||||
|
|
||||||
if (config.threads != 1)
|
|
||||||
pthread_mutex_unlock(&rawsocket_lock);
|
|
||||||
|
|
||||||
/* The function will return -errno on error as well as errno value set itself */
|
|
||||||
if (sent < 0) sent = -errno;
|
|
||||||
|
|
||||||
return sent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -471,6 +579,12 @@ int main(int argc, char *argv[]) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (open_raw6_socket() < 0) {
|
||||||
|
perror("Unable to open raw socket for ipv6");
|
||||||
|
close_raw_socket();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
struct queue_res *qres = &defqres;
|
struct queue_res *qres = &defqres;
|
||||||
|
|
||||||
if (config.threads == 1) {
|
if (config.threads == 1) {
|
||||||
@ -503,10 +617,8 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close_raw_socket() < 0) {
|
close_raw_socket();
|
||||||
perror("Unable to close raw socket");
|
close_raw6_socket();
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -qres->status;
|
return -qres->status;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user