mirror of
https://github.com/Waujito/youtubeUnblock.git
synced 2024-12-22 22:36:03 +00:00
Use TCP Segmentation
This commit is proposed to be a fix of #1. Some DPIs drops IP fragmented packets so we are going to higher level and fragmenting TCPs. Fragmented TCPs are normally handled by DPIs but if they are going in reversed order everything is ok. In further reviews of this technique may be a delay for 2nd packet should be implemented.
This commit is contained in:
parent
4a4519cbac
commit
d2985e80bd
130
youtubeUnblock.c
130
youtubeUnblock.c
@ -20,9 +20,11 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#ifndef NOUSE_GSO
|
#ifndef NOUSE_GSO
|
||||||
|
|
||||||
#define USE_GSO
|
#define USE_GSO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USE_IP_FRAGMENTATION
|
||||||
|
#define USE_TCP_SEGMENTATION
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RAWSOCKET_MARK 0xfc70
|
#define RAWSOCKET_MARK 0xfc70
|
||||||
@ -207,8 +209,6 @@ static int ipv4_frag(struct pkt_buff *pktb, size_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);
|
||||||
|
|
||||||
*frag1 = pktb_alloc(AF_INET, buff1, f1_dlen, 256);
|
|
||||||
*frag2 = pktb_alloc(AF_INET, buff2, f2_dlen, 256);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("Packet split in portion %zu %zu\n", f1_dlen, f2_dlen);
|
printf("Packet split in portion %zu %zu\n", f1_dlen, f2_dlen);
|
||||||
@ -217,6 +217,82 @@ static int ipv4_frag(struct pkt_buff *pktb, size_t payload_offset,
|
|||||||
nfq_ip_set_checksum(f1_hdr);
|
nfq_ip_set_checksum(f1_hdr);
|
||||||
nfq_ip_set_checksum(f2_hdr);
|
nfq_ip_set_checksum(f2_hdr);
|
||||||
|
|
||||||
|
*frag1 = pktb_alloc(AF_INET, buff1, f1_dlen, 256);
|
||||||
|
*frag2 = pktb_alloc(AF_INET, buff2, f2_dlen, 256);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// split packet to two tcp-on-ipv4 segments.
|
||||||
|
static int tcp4_frag(struct pkt_buff *pktb, size_t payload_offset,
|
||||||
|
struct pkt_buff **seg1, struct pkt_buff **seg2) {
|
||||||
|
uint8_t buff1[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
uint8_t buff2[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
struct iphdr *hdr = nfq_ip_get_hdr(pktb);
|
||||||
|
size_t hdr_len = hdr->ihl * 4;
|
||||||
|
if (hdr == NULL) {errno = EINVAL; return -1;}
|
||||||
|
if (hdr->protocol != IPPROTO_TCP || !(ntohs(hdr->frag_off) & IP_DF)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nfq_ip_set_transport_header(pktb, hdr))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
struct tcphdr *tcph = nfq_tcp_get_hdr(pktb);
|
||||||
|
size_t tcph_len = tcph->doff * 4;
|
||||||
|
if (tcph == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *payload = nfq_tcp_get_payload(tcph, pktb);
|
||||||
|
size_t plen = nfq_tcp_get_payload_len(tcph, pktb);
|
||||||
|
|
||||||
|
if (hdr == NULL || payload == NULL || plen <= payload_offset) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t s1_plen = payload_offset;
|
||||||
|
size_t s1_dlen = s1_plen + hdr_len + tcph_len;
|
||||||
|
|
||||||
|
size_t s2_plen = plen - payload_offset;
|
||||||
|
size_t s2_dlen = s2_plen + hdr_len + tcph_len;
|
||||||
|
|
||||||
|
memcpy(buff1, hdr, hdr_len);
|
||||||
|
memcpy(buff2, hdr, hdr_len);
|
||||||
|
|
||||||
|
memcpy(buff1 + hdr_len, tcph, tcph_len);
|
||||||
|
memcpy(buff2 + hdr_len, tcph, tcph_len);
|
||||||
|
|
||||||
|
memcpy(buff1 + hdr_len + tcph_len, payload, s1_plen);
|
||||||
|
memcpy(buff2 + hdr_len + tcph_len, payload + payload_offset, s2_plen);
|
||||||
|
|
||||||
|
struct iphdr *s1_hdr = (void *)buff1;
|
||||||
|
struct iphdr *s2_hdr = (void *)buff2;
|
||||||
|
|
||||||
|
struct tcphdr *s1_tcph = (void *)(buff1 + hdr_len);
|
||||||
|
struct tcphdr *s2_tcph = (void *)(buff2 + hdr_len);
|
||||||
|
|
||||||
|
s1_hdr->tot_len = htons(s1_dlen);
|
||||||
|
s2_hdr->tot_len = htons(s2_dlen);
|
||||||
|
|
||||||
|
// s2_hdr->id = htons(ntohs(s1_hdr->id) + 1);
|
||||||
|
s2_tcph->seq = htonl(ntohl(s2_tcph->seq) + payload_offset);
|
||||||
|
// printf("%zu %du %du\n", payload_offset, ntohs(s1_tcph->seq), ntohs(s2_tcph->seq));
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("Packet split in portion %zu %zu\n", s1_dlen, s2_dlen);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
nfq_tcp_compute_checksum_ipv4(s1_tcph, s1_hdr);
|
||||||
|
nfq_tcp_compute_checksum_ipv4(s2_tcph, s2_hdr);
|
||||||
|
|
||||||
|
*seg1 = pktb_alloc(AF_INET, buff1, s1_dlen, 256);
|
||||||
|
*seg2 = pktb_alloc(AF_INET, buff2, s2_dlen, 256);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +307,11 @@ static int send_raw_socket(struct pkt_buff *pktb) {
|
|||||||
struct pkt_buff *buff1;
|
struct pkt_buff *buff1;
|
||||||
struct pkt_buff *buff2;
|
struct pkt_buff *buff2;
|
||||||
|
|
||||||
ipv4_frag(pktb, AVAILABLE_MTU-24, &buff1, &buff2);
|
#ifdef USE_TCP_SEGMENTATION
|
||||||
|
tcp4_frag(pktb, AVAILABLE_MTU-128, &buff1, &buff2);
|
||||||
|
#else
|
||||||
|
ipv4_frag(pktb, AVAILABLE_MTU-128, &buff1, &buff2);
|
||||||
|
#endif
|
||||||
|
|
||||||
int sent = 0;
|
int sent = 0;
|
||||||
int status = send_raw_socket(buff1);
|
int status = send_raw_socket(buff1);
|
||||||
@ -242,16 +322,14 @@ static int send_raw_socket(struct pkt_buff *pktb) {
|
|||||||
pktb_free(buff2);
|
pktb_free(buff2);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
pktb_free(buff1);
|
||||||
|
|
||||||
status = send_raw_socket(buff2);
|
status = send_raw_socket(buff2);
|
||||||
if (status >= 0) sent += status;
|
if (status >= 0) sent += status;
|
||||||
else {
|
else {
|
||||||
pktb_free(buff1);
|
|
||||||
pktb_free(buff2);
|
pktb_free(buff2);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
pktb_free(buff1);
|
|
||||||
pktb_free(buff2);
|
pktb_free(buff2);
|
||||||
|
|
||||||
return sent;
|
return sent;
|
||||||
@ -543,17 +621,35 @@ static int process_packet(const struct packet_data packet) {
|
|||||||
// Also it will never be meaningless to ensure the
|
// Also it will never be meaningless to ensure the
|
||||||
// checksum is right.
|
// checksum is right.
|
||||||
nfq_tcp_compute_checksum_ipv4(tcph, ip_header);
|
nfq_tcp_compute_checksum_ipv4(tcph, ip_header);
|
||||||
|
|
||||||
nfq_nlmsg_verdict_put(verdnlh, packet.id, NF_DROP);
|
nfq_nlmsg_verdict_put(verdnlh, packet.id, NF_DROP);
|
||||||
|
|
||||||
size_t ipd_offset = ((char *)data - (char *)tcph) + vrd.sni_offset;
|
|
||||||
|
|
||||||
size_t mid_offset = ipd_offset + vrd.sni_len / 2;
|
|
||||||
mid_offset += 8 - mid_offset % 8;
|
|
||||||
|
|
||||||
struct pkt_buff *frag1;
|
struct pkt_buff *frag1;
|
||||||
struct pkt_buff *frag2;
|
struct pkt_buff *frag2;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_TCP_SEGMENTATION
|
||||||
|
size_t ipd_offset = vrd.sni_offset;
|
||||||
|
size_t mid_offset = ipd_offset + vrd.sni_len / 2;
|
||||||
|
|
||||||
|
if (tcp4_frag(pktb, mid_offset, &frag1, &frag2) < 0) {
|
||||||
|
perror("tcp4_frag");
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((send_raw_socket(frag2) == -1) || (send_raw_socket(frag1) == -1)) {
|
||||||
|
perror("raw frags send");
|
||||||
|
}
|
||||||
|
|
||||||
|
pktb_free(frag1);
|
||||||
|
pktb_free(frag2);
|
||||||
|
|
||||||
|
#else
|
||||||
|
size_t ipd_offset = ((char *)data - (char *)tcph) + vrd.sni_offset;
|
||||||
|
size_t mid_offset = ipd_offset + vrd.sni_len / 2;
|
||||||
|
mid_offset += 8 - mid_offset % 8;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (ipv4_frag(pktb, mid_offset, &frag1, &frag2) < 0) {
|
if (ipv4_frag(pktb, mid_offset, &frag1, &frag2) < 0) {
|
||||||
perror("ipv4_frag");
|
perror("ipv4_frag");
|
||||||
goto fallback;
|
goto fallback;
|
||||||
@ -565,6 +661,8 @@ static int process_packet(const struct packet_data packet) {
|
|||||||
|
|
||||||
pktb_free(frag1);
|
pktb_free(frag1);
|
||||||
pktb_free(frag2);
|
pktb_free(frag2);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -648,6 +746,12 @@ int main(int argc, const char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_TCP_SEGMENTATION
|
||||||
|
printf("Using TCP segmentation!\n");
|
||||||
|
#else
|
||||||
|
printf("Using IP fragmentation!\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
if (open_socket()) {
|
if (open_socket()) {
|
||||||
perror("Unable to open socket");
|
perror("Unable to open socket");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
Loading…
Reference in New Issue
Block a user