diff --git a/src/kytunblock.c b/src/kytunblock.c index 78e6ae3..54dbcfa 100644 --- a/src/kytunblock.c +++ b/src/kytunblock.c @@ -195,21 +195,21 @@ static int send_raw_socket(const uint8_t *pkt, size_t pktlen) { int ret; if (pktlen > AVAILABLE_MTU) { - lgdebug("The packet is too big and may cause issues!"); + lgtrace("Split packet!"); - NETBUF_ALLOC(buff1, MAX_PACKET_SIZE); - if (!NETBUF_CHECK(buff1)) { + size_t buff1_size = pktlen; + uint8_t *buff1 = malloc(buff1_size); + if (buff1 == NULL) { lgerror(-ENOMEM, "Allocation error"); return -ENOMEM; } - NETBUF_ALLOC(buff2, MAX_PACKET_SIZE); - if (!NETBUF_CHECK(buff2)) { + size_t buff2_size = pktlen; + uint8_t *buff2 = malloc(buff2_size); + if (buff2 == NULL) { lgerror(-ENOMEM, "Allocation error"); - NETBUF_FREE(buff2); + free(buff1); return -ENOMEM; } - size_t buff1_size = MAX_PACKET_SIZE; - size_t buff2_size = MAX_PACKET_SIZE; if ((ret = tcp_frag(pkt, pktlen, AVAILABLE_MTU-128, buff1, &buff1_size, buff2, &buff2_size)) < 0) { @@ -231,12 +231,12 @@ static int send_raw_socket(const uint8_t *pkt, size_t pktlen) { goto erret_lc; } - NETBUF_FREE(buff1); - NETBUF_FREE(buff2); + free(buff1); + free(buff2); return sent; erret_lc: - NETBUF_FREE(buff1); - NETBUF_FREE(buff2); + free(buff1); + free(buff2); return ret; } diff --git a/src/mangle.c b/src/mangle.c index 9f5cf86..b1725e2 100644 --- a/src/mangle.c +++ b/src/mangle.c @@ -211,32 +211,32 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra if (ret < 0) { - goto accept; + return PKT_ACCEPT; } // As defined by TLS standard. if (section->dport_filter && ntohs(tcph->dest) != 443) { - goto accept; + return PKT_ACCEPT; } if (tcph->syn && section->synfake) { lgtrace_addp("TCP syn alter"); - NETBUF_ALLOC(payload, MAX_PACKET_SIZE); - if (!NETBUF_CHECK(payload)) { - lgerror(-ENOMEM, "Allocation error"); - goto accept; - } - - memcpy(payload, ipxh, iph_len); - memcpy(payload + iph_len, tcph, tcph_len); size_t fake_len = section->fake_sni_pkt_sz; - if (section->synfake_len) fake_len = min(section->synfake_len, fake_len); - memcpy(payload + iph_len + tcph_len, section->fake_sni_pkt, fake_len); + size_t payload_len = iph_len + tcph_len + fake_len; + uint8_t *payload = malloc(payload_len); + if (payload == NULL) { + lgerror(-ENOMEM, "Allocation error"); + return PKT_ACCEPT; + } + + memcpy(payload, ipxh, iph_len); + memcpy(payload + iph_len, tcph, tcph_len); + memcpy(payload + iph_len + tcph_len, section->fake_sni_pkt, fake_len); struct tcphdr *tcph = (struct tcphdr *)(payload + iph_len); if (ipxv == IP4VERSION) { @@ -252,22 +252,23 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra } - ret = instance_config.send_raw_packet(payload, iph_len + tcph_len + fake_len); + ret = instance_config.send_raw_packet(payload, payload_len); if (ret < 0) { lgerror(ret, "send_syn_altered"); - NETBUF_FREE(payload); - goto accept; + free(payload); + return PKT_ACCEPT; } - NETBUF_FREE(payload); - goto drop; + free(payload); + return PKT_DROP; } - if (tcph->syn) goto continue_flow; + if (tcph->syn) + return PKT_CONTINUE; if (!section->tls_enabled) - goto continue_flow; + return PKT_CONTINUE; struct tls_verdict vrd = analyze_tls_data(section, data, dlen); lgtrace_addp("TLS analyzed"); @@ -282,12 +283,11 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra size_t target_sni_offset = vrd.target_sni_ptr - data; size_t payload_len = raw_payload_len; - NETBUF_ALLOC(payload, MAX_PACKET_SIZE); - if (!NETBUF_CHECK(payload)) { + uint8_t *payload = malloc(raw_payload_len); + if (payload == NULL) { lgerror(-ENOMEM, "Allocation error"); - goto accept; + return PKT_ACCEPT; } - memcpy(payload, raw_payload, raw_payload_len); void *iph; @@ -311,6 +311,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra set_tcp_checksum(tcph, iph, iph_len); } +/* if (0) { int delta = 2; ret = seqovl_packet(payload, &payload_len, delta); @@ -321,116 +322,108 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra lgerror(ret, "seqovl_packet delta %d", delta); } } - +*/ - if (dlen > 1480 && config.verbose) { + if (dlen > AVAILABLE_MTU) { lgdebug("WARNING! Client Hello packet is too big and may cause issues!"); } if (section->fake_sni) { - post_fake_sni(args_default_fake_type(section), iph, iph_len, tcph, tcph_len); + post_fake_sni(args_default_fake_type(section), iph, iph_len, tcph, tcph_len); } size_t ipd_offset; size_t mid_offset; switch (section->fragmentation_strategy) { - case FRAG_STRAT_TCP: { - ipd_offset = target_sni_offset; - mid_offset = ipd_offset + vrd.target_sni_len / 2; + case FRAG_STRAT_TCP: + { + ipd_offset = target_sni_offset; + mid_offset = ipd_offset + vrd.target_sni_len / 2; - size_t poses[2]; - int cnt = 0; + size_t poses[2]; + int cnt = 0; - if (section->frag_sni_pos && dlen > section->frag_sni_pos) { - poses[cnt++] = section->frag_sni_pos; - } - - if (section->frag_middle_sni) { - poses[cnt++] = mid_offset; - } - - if (cnt > 1 && poses[0] > poses[1]) { - size_t tmp = poses[0]; - poses[0] = poses[1]; - poses[1] = tmp; - } - - ret = send_tcp_frags(section, payload, payload_len, poses, cnt, 0); - if (ret < 0) { - lgerror(ret, "tcp4 send frags"); - goto accept_lc; - } - - goto drop_lc; + if (section->frag_sni_pos && dlen > section->frag_sni_pos) { + poses[cnt++] = section->frag_sni_pos; } - break; - case FRAG_STRAT_IP: - if (ipxv == IP4VERSION) { - ipd_offset = ((char *)data - (char *)tcph) + target_sni_offset; - mid_offset = ipd_offset + vrd.target_sni_len / 2; - mid_offset += 8 - mid_offset % 8; - size_t poses[2]; - int cnt = 0; - - if (section->frag_sni_pos && dlen > section->frag_sni_pos) { - poses[cnt] = section->frag_sni_pos + ((char *)data - (char *)tcph); - poses[cnt] += 8 - poses[cnt] % 8; - cnt++; - } - - if (section->frag_middle_sni) { - poses[cnt++] = mid_offset; - } - - if (cnt > 1 && poses[0] > poses[1]) { - size_t tmp = poses[0]; - poses[0] = poses[1]; - poses[1] = tmp; - } - - ret = send_ip4_frags(section, payload, payload_len, poses, cnt, 0); - if (ret < 0) { - lgerror(ret, "ip4 send frags"); - goto accept_lc; - } - - goto drop_lc; - } else { - lginfo("WARNING: IP fragmentation is supported only for IPv4"); - goto default_send; + if (section->frag_middle_sni) { + poses[cnt++] = mid_offset; } - default: - default_send: - ret = instance_config.send_raw_packet(payload, payload_len); - if (ret < 0) { - lgerror(ret, "raw pack send"); - goto accept_lc; - } - goto drop_lc; + if (cnt > 1 && poses[0] > poses[1]) { + size_t tmp = poses[0]; + poses[0] = poses[1]; + poses[1] = tmp; + } + + ret = send_tcp_frags(section, payload, payload_len, poses, cnt, 0); + if (ret < 0) { + lgerror(ret, "tcp4 send frags"); + goto accept_lc; + } + + goto drop_lc; + } + break; + case FRAG_STRAT_IP: + if (ipxv == IP4VERSION) { + ipd_offset = ((char *)data - (char *)tcph) + target_sni_offset; + mid_offset = ipd_offset + vrd.target_sni_len / 2; + mid_offset += 8 - mid_offset % 8; + + size_t poses[2]; + int cnt = 0; + + if (section->frag_sni_pos && dlen > section->frag_sni_pos) { + poses[cnt] = section->frag_sni_pos + ((char *)data - (char *)tcph); + poses[cnt] += 8 - poses[cnt] % 8; + cnt++; + } + + if (section->frag_middle_sni) { + poses[cnt++] = mid_offset; + } + + if (cnt > 1 && poses[0] > poses[1]) { + size_t tmp = poses[0]; + poses[0] = poses[1]; + poses[1] = tmp; + } + + ret = send_ip4_frags(section, payload, payload_len, poses, cnt, 0); + if (ret < 0) { + lgerror(ret, "ip4 send frags"); + goto accept_lc; + } + + goto drop_lc; + } else { + lginfo("WARNING: IP fragmentation is supported only for IPv4"); + goto default_send; + } + break; } - +default_send: + ret = instance_config.send_raw_packet(payload, payload_len); + if (ret < 0) { + lgerror(ret, "raw pack send"); + goto accept_lc; + } goto drop_lc; accept_lc: - NETBUF_FREE(payload); - goto accept; + free(payload); + return PKT_ACCEPT; drop_lc: - NETBUF_FREE(payload); - goto drop; - + free(payload); + return PKT_DROP; } -continue_flow: return PKT_CONTINUE; -accept: - return PKT_ACCEPT; -drop: - return PKT_DROP; } int process_udp_packet(const struct section_config_t *section, const uint8_t *pkt, size_t pktlen) { @@ -458,12 +451,8 @@ int process_udp_packet(const struct section_config_t *section, const uint8_t *pk goto drop; else if (section->udp_mode == UDP_MODE_FAKE) { for (int i = 0; i < section->udp_fake_seq_len; i++) { - NETBUF_ALLOC(fake_udp, MAX_PACKET_SIZE); - if (!NETBUF_CHECK(fake_udp)) { - lgerror(-ENOMEM, "Allocation error"); - return -ENOMEM; - } - size_t fsn_len = MAX_PACKET_SIZE; + uint8_t *fake_udp; + size_t fake_udp_len; struct udp_fake_type fake_type = { .fake_len = section->udp_fake_len, @@ -472,24 +461,25 @@ int process_udp_packet(const struct section_config_t *section, const uint8_t *pk .faking_ttl = section->faking_ttl, }, }; - ret = gen_fake_udp(fake_type, iph, iph_len, udph, fake_udp, &fsn_len); + ret = gen_fake_udp(fake_type, iph, iph_len, udph, &fake_udp, &fake_udp_len); if (ret < 0) { lgerror(ret, "gen_fake_udp"); - goto erret_lc; + goto erret; } lgtrace_addp("post fake udp #%d", i + 1); - ret = instance_config.send_raw_packet(fake_udp, fsn_len); + ret = instance_config.send_raw_packet(fake_udp, fake_udp_len); if (ret < 0) { lgerror(ret, "send fake udp"); goto erret_lc; } - NETBUF_FREE(fake_udp); + free(fake_udp); continue; erret_lc: - NETBUF_FREE(fake_udp); + free(fake_udp); +erret: goto accept; } @@ -524,33 +514,21 @@ int send_ip4_frags(const struct section_config_t *section, const uint8_t *packet packet, pktlen); } } else { - NETBUF_ALLOC(frag1, MAX_PACKET_SIZE); - if (!NETBUF_CHECK(frag1)) { + size_t f1len = pktlen; + uint8_t *frag1 = malloc(f1len); + if (frag1 == NULL) { lgerror(-ENOMEM, "Allocation error"); return -ENOMEM; } - NETBUF_ALLOC(frag2, MAX_PACKET_SIZE); - if (!NETBUF_CHECK(frag2)) { + size_t f2len = pktlen; + uint8_t *frag2 = malloc(f2len); + if (frag2 == NULL) { lgerror(-ENOMEM, "Allocation error"); - NETBUF_FREE(frag1); + free(frag1); return -ENOMEM; } -/* - NETBUF_ALLOC(fake_pad, MAX_PACKET_SIZE); - if (!NETBUF_CHECK(fake_pad)) { - lgerror(-ENOMEM, "Allocation error"); - NETBUF_FREE(frag1); - NETBUF_FREE(frag2); - return -ENOMEM; - } -*/ - - size_t f1len = MAX_PACKET_SIZE; - size_t f2len = MAX_PACKET_SIZE; - // size_t fake_pad_len = MAX_PACKET_SIZE; - int ret; if (dvs > poses[0]) { @@ -570,8 +548,6 @@ int send_ip4_frags(const struct section_config_t *section, const uint8_t *packet goto erret_lc; } - dvs += frag_pos; - if (section->frag_sni_reverse) goto send_frag2; send_frag1: @@ -583,54 +559,22 @@ send_frag1: if (section->frag_sni_reverse) goto out_lc; -send_fake: -/* - if (section->frag_sni_faked) { - ITER_FAKE_STRAT(section->faking_strategy, strategy) { - size_t iphfl; - fake_pad_len = f2len; - ret = ip4_payload_split(frag2, f2len, NULL, &iphfl, NULL, NULL); - if (ret < 0) { - lgerror("Invalid frag2", ret); - goto erret_lc; - } - memcpy(fake_pad, frag2, iphfl + sizeof(struct udphdr)); - memset(fake_pad + iphfl + sizeof(struct udphdr), 0, f2len - iphfl - sizeof(struct udphdr)); - ((struct iphdr *)fake_pad)->tot_len = htons(fake_pad_len); - ((struct iphdr *)fake_pad)->id = 1; - ((struct iphdr *)fake_pad)->ttl = 8; - ((struct iphdr *)fake_pad)->frag_off = 0; - ip4_set_checksum((struct iphdr*)fake_pad); - // *(struct udphdr *)(fake_pad + iphfl) = *(struct udphdr *)(frag2 + iphfl); - ret = send_ip4_frags(fake_pad, fake_pad_len, NULL, 0, 0); - if (ret < 0) { - goto erret_lc; - } - } - } -*/ - - if (section->frag_sni_reverse) - goto send_frag1; - send_frag2: - ret = send_ip4_frags(section, frag2, f2len, poses + 1, poses_sz - 1, dvs); + ret = send_ip4_frags(section, frag2, f2len, poses + 1, poses_sz - 1, poses[0]); if (ret < 0) { goto erret_lc; } if (section->frag_sni_reverse) - goto send_fake; + goto send_frag1; out_lc: - NETBUF_FREE(frag1); - NETBUF_FREE(frag2); - // NETBUF_FREE(fake_pad); + free(frag1); + free(frag2); goto out; erret_lc: - NETBUF_FREE(frag1); - NETBUF_FREE(frag2); - // NETBUF_FREE(fake_pad); + free(frag1); + free(frag2); return ret; } @@ -656,22 +600,21 @@ int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet packet, pktlen); } } else { - NETBUF_ALLOC(frag1, MAX_PACKET_SIZE); - if (!NETBUF_CHECK(frag1)) { + size_t f1len = pktlen; + uint8_t *frag1 = malloc(f1len); + if (frag1 == NULL) { lgerror(-ENOMEM, "Allocation error"); return -ENOMEM; } - NETBUF_ALLOC(frag2, MAX_PACKET_SIZE); - if (!NETBUF_CHECK(frag2)) { + size_t f2len = pktlen; + uint8_t *frag2 = malloc(f2len); + if (frag2 == NULL) { lgerror(-ENOMEM, "Allocation error"); - NETBUF_FREE(frag1); + free(frag1); return -ENOMEM; } - size_t f1len = MAX_PACKET_SIZE; - size_t f2len = MAX_PACKET_SIZE; - int ret; if (dvs > poses[0]) { @@ -680,7 +623,6 @@ int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet goto erret_lc; } - ret = tcp_frag(packet, pktlen, poses[0] - dvs, frag1, &f1len, frag2, &f2len); @@ -697,16 +639,14 @@ int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet goto send_frag2; send_frag1: - { - ret = send_tcp_frags(section, frag1, f1len, NULL, 0, 0); - if (ret < 0) { - goto erret_lc; - } - - if (section->frag_sni_reverse) - goto out_lc; + ret = send_tcp_frags(section, frag1, f1len, NULL, 0, 0); + if (ret < 0) { + goto erret_lc; } + if (section->frag_sni_reverse) + goto out_lc; + send_fake: if (section->frag_sni_faked) { size_t iphfl, tcphfl; @@ -729,22 +669,20 @@ send_fake: goto send_frag1; send_frag2: - { - ret = send_tcp_frags(section, frag2, f2len, poses + 1, poses_sz - 1, poses[0]); - if (ret < 0) { - goto erret_lc; - } - - if (section->frag_sni_reverse) - goto send_fake; + ret = send_tcp_frags(section, frag2, f2len, poses + 1, poses_sz - 1, poses[0]); + if (ret < 0) { + goto erret_lc; } + + if (section->frag_sni_reverse) + goto send_fake; out_lc: - NETBUF_FREE(frag1); - NETBUF_FREE(frag2); + free(frag1); + free(frag2); goto out; erret_lc: - NETBUF_FREE(frag1); - NETBUF_FREE(frag2); + free(frag1); + free(frag2); return ret; } out: @@ -773,28 +711,24 @@ int post_fake_sni(struct fake_type f_type, // one goes for default fake for (int i = 0; i < fake_seq_type.sequence_len; i++) { - NETBUF_ALLOC(fake_sni, MAX_PACKET_SIZE); - if (!NETBUF_CHECK(fake_sni)) { - lgerror(-ENOMEM, "Allocation error"); - return -ENOMEM; - } - size_t fsn_len = MAX_PACKET_SIZE; - + uint8_t *fake_sni; + size_t fake_sni_len; + ret = gen_fake_sni( fake_seq_type, fsiph, iph_len, fstcph, tcph_len, - fake_sni, &fsn_len); + &fake_sni, &fake_sni_len); if (ret < 0) { lgerror(ret, "gen_fake_sni"); - goto erret_lc; + return ret; } lgtrace_addp("post fake sni #%d", i + 1); if (f_type.seg2delay) { - ret = instance_config.send_delayed_packet(fake_sni, fsn_len, f_type.seg2delay); + ret = instance_config.send_delayed_packet(fake_sni, fake_sni_len, f_type.seg2delay); } else { - ret = instance_config.send_raw_packet(fake_sni, fsn_len); + ret = instance_config.send_raw_packet(fake_sni, fake_sni_len); } if (ret < 0) { lgerror(ret, "send fake sni"); @@ -804,7 +738,7 @@ int post_fake_sni(struct fake_type f_type, size_t tcph_len; size_t plen; ret = tcp_payload_split( - fake_sni, fsn_len, + fake_sni, fake_sni_len, &fsiph, &iph_len, &fstcph, &tcph_len, NULL, &plen); @@ -830,10 +764,10 @@ int post_fake_sni(struct fake_type f_type, fsiph = (void *)rfsiph; fstcph = (void *)rfstcph; - NETBUF_FREE(fake_sni); + free(fake_sni); continue; erret_lc: - NETBUF_FREE(fake_sni); + free(fake_sni); return ret; } } diff --git a/src/quic.c b/src/quic.c index 5d896c3..28e5da1 100644 --- a/src/quic.c +++ b/src/quic.c @@ -285,13 +285,25 @@ int udp_fail_packet(struct udp_failing_strategy strategy, uint8_t *payload, size int gen_fake_udp(struct udp_fake_type type, const void *ipxh, size_t iph_len, const struct udphdr *udph, - uint8_t *buf, size_t *buflen) { + uint8_t **ubuf, size_t *ubuflen) { size_t data_len = type.fake_len; + int ret; - if (!ipxh || !udph || !buf || !buflen) + if (!ipxh || !udph || !ubuf || !ubuflen) return -EINVAL; int ipxv = netproto_version(ipxh, iph_len); + + if (ipxv == IP6VERSION) { + iph_len = sizeof(struct ip6_hdr); + } + + size_t dlen = iph_len + sizeof(struct udphdr) + data_len; + size_t buffer_len = dlen + 50; + uint8_t *buf = malloc(buffer_len); + if (buf == NULL) { + return -ENOMEM; + } if (ipxv == IP4VERSION) { const struct iphdr *iph = ipxh; @@ -303,20 +315,15 @@ int gen_fake_udp(struct udp_fake_type type, } 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; + ret = -EINVAL; + goto error; } - size_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); @@ -336,11 +343,19 @@ int gen_fake_udp(struct udp_fake_type type, set_udp_checksum(nudph, buf, iph_len); - udp_fail_packet(type.strategy, buf, &dlen, *buflen); + ret = udp_fail_packet(type.strategy, buf, &dlen, buffer_len); + if (ret < 0) { + lgerror(ret, "udp_fail_packet"); + goto error; + } - *buflen = dlen; + *ubuflen = dlen; + *ubuf = buf; return 0; +error: + free(buf); + return ret; } int parse_quic_decrypted( diff --git a/src/quic.h b/src/quic.h index 5478101..f184c23 100644 --- a/src/quic.h +++ b/src/quic.h @@ -234,11 +234,11 @@ int parse_quic_decrypted( // Like fail_packet for TCP int udp_fail_packet(struct udp_failing_strategy strategy, uint8_t *payload, size_t *plen, size_t avail_buflen); -// Like gen_fake_sni for TCP +// Like gen_fake_sni for TCP, Allocates and generates udp fake int gen_fake_udp(struct udp_fake_type type, const void *ipxh, size_t iph_len, const struct udphdr *udph, - uint8_t *buf, size_t *buflen); + uint8_t **buf, size_t *buflen); int detect_udp_filtered(const struct section_config_t *section, const uint8_t *payload, size_t plen); diff --git a/src/tls.c b/src/tls.c index 6e3eb36..c0c9043 100644 --- a/src/tls.c +++ b/src/tls.c @@ -41,27 +41,28 @@ int bruteforce_analyze_sni_str( vrd->sni_ptr = data + dlen / 2; return 0; } + int max_domain_len = 0; + for (struct domains_list *sne = section->sni_domains; sne != NULL; + sne = sne->next) { + max_domain_len = max(sne->domain_len, max_domain_len); + } + + size_t buf_size = max_domain_len + dlen + 1; + uint8_t *buf = malloc(buf_size); + if (buf == NULL) { + return -ENOMEM; + } + int *nzbuf = malloc(buf_size * sizeof(int)); + if (nzbuf == NULL) { + free(buf); + return -ENOMEM; + } + for (struct domains_list *sne = section->sni_domains; sne != NULL; sne = sne->next) { const char *domain_startp = sne->domain_name; int domain_len = sne->domain_len; - if (sne->domain_len + dlen + 1 > MAX_PACKET_SIZE) { - continue; - } - - NETBUF_ALLOC(buf, MAX_PACKET_SIZE); - if (!NETBUF_CHECK(buf)) { - lgerror(-ENOMEM, "Allocation error"); - return -ENOMEM; - } - NETBUF_ALLOC(nzbuf, MAX_PACKET_SIZE * sizeof(int)); - if (!NETBUF_CHECK(nzbuf)) { - lgerror(-ENOMEM, "Allocation error"); - NETBUF_FREE(buf); - return -ENOMEM; - } - int *zbuf = (void *)nzbuf; memcpy(buf, domain_startp, domain_len); @@ -77,17 +78,13 @@ int bruteforce_analyze_sni_str( vrd->sni_ptr = data + (k - domain_len - 1); vrd->target_sni_ptr = vrd->sni_ptr; vrd->target_sni_len = vrd->sni_len; - NETBUF_FREE(buf); - NETBUF_FREE(nzbuf); - return 0; + goto return_vrd; } } - - - NETBUF_FREE(buf); - NETBUF_FREE(nzbuf); } - +return_vrd: + free(buf); + free(nzbuf); return 0; } static int analyze_sni_str( @@ -319,18 +316,31 @@ out: int gen_fake_sni(struct fake_type type, const void *ipxh, size_t iph_len, const struct tcphdr *tcph, size_t tcph_len, - uint8_t *buf, size_t *buflen) { + uint8_t **ubuf, size_t *ubuflen) { size_t data_len = type.fake_len; + uint8_t *buf = NULL; + int ret; if (type.type == FAKE_PAYLOAD_RANDOM && data_len == 0) { data_len = (size_t)randint() % 1200; } - if (!ipxh || !tcph || !buf || !buflen) + if (!ipxh || !tcph || !ubuf || !ubuflen) return -EINVAL; int ipxv = netproto_version(ipxh, iph_len); + if (ipxv == IP6VERSION) { + iph_len = sizeof(struct ip6_hdr); + } + + size_t dlen = iph_len + tcph_len + data_len; + size_t buffer_len = dlen + 50; + buf = malloc(buffer_len); + if (buf == NULL) { + return -ENOMEM; + } + if (ipxv == IP4VERSION) { const struct iphdr *iph = ipxh; @@ -341,20 +351,15 @@ int gen_fake_sni(struct fake_type type, } 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_TCP; } else { - return -EINVAL; + ret = -EINVAL; + goto error; } - size_t dlen = iph_len + tcph_len + data_len; - - if (*buflen < dlen) - return -ENOMEM; - memcpy(buf + iph_len, tcph, tcph_len); uint8_t *bfdptr = buf + iph_len + tcph_len; @@ -391,10 +396,19 @@ int gen_fake_sni(struct fake_type type, niph->ip6_plen = htons(dlen - iph_len); } - fail_packet(type.strategy, buf, &dlen, *buflen); + ret = fail_packet(type.strategy, buf, &dlen, buffer_len); + if (ret < 0) { + lgerror(ret, "fail_packet"); + goto error; + } - *buflen = dlen; + + *ubuflen = dlen; + *ubuf = buf; return 0; +error: + free(buf); + return ret; } diff --git a/src/tls.h b/src/tls.h index 6f96fcc..427fa91 100644 --- a/src/tls.h +++ b/src/tls.h @@ -75,11 +75,11 @@ struct tls_verdict analyze_tls_data(const struct section_config_t *section, cons /** - * Generates the fake client hello message + * Allocates and generates the fake client hello message */ int gen_fake_sni(struct fake_type type, const void *iph, size_t iph_len, const struct tcphdr *tcph, size_t tcph_len, - uint8_t *buf, size_t *buflen); + uint8_t **ubuf, size_t *ubuflen); #endif /* TLS_H */ diff --git a/src/types.h b/src/types.h index fdf824e..0dc9705 100644 --- a/src/types.h +++ b/src/types.h @@ -126,31 +126,6 @@ free((item)); \ #endif /* not a KERNEL_SPACE */ -/* An alternative memory allocation strategy for userspace app */ -// #define ALLOC_MALLOC - -/** - * Use NETBUF_ALLOC and NETBUF_FREE as an abstraction of memory allocation. - * Do not use it within expressions, consider these defines as separate statements. - * - * Use NETBUF_CHECK to check that buffer was properly allocated. - */ -#ifdef KERNEL_SPACE -#include -#define NETBUF_ALLOC(buf, buf_len) __u8* buf = kmalloc(buf_len, GFP_KERNEL); -#define NETBUF_CHECK(buf) ((buf) != NULL) -#define NETBUF_FREE(buf) kfree(buf); -#elif defined(ALLOC_MALLOC) -#include -#define NETBUF_ALLOC(buf, buf_len) __u8* buf = malloc(buf_len); -#define NETBUF_CHECK(buf) ((buf) != NULL) -#define NETBUF_FREE(buf) free(buf); -#else -#define NETBUF_ALLOC(buf, buf_len) __u8 buf[buf_len]; -#define NETBUF_CHECK(buf) (1) -#define NETBUF_FREE(buf) ; -#endif - static inline int randint(void) { int rnd; diff --git a/src/youtubeUnblock.c b/src/youtubeUnblock.c index 1fe671f..9b941df 100644 --- a/src/youtubeUnblock.c +++ b/src/youtubeUnblock.c @@ -501,50 +501,46 @@ static int send_raw_socket(const uint8_t *pkt, size_t pktlen) { if (pktlen > AVAILABLE_MTU) { lgtrace("Split packet!"); - NETBUF_ALLOC(buff1, MNL_SOCKET_BUFFER_SIZE); - if (!NETBUF_CHECK(buff1)) { + size_t buff1_size = pktlen; + uint8_t *buff1 = malloc(buff1_size); + if (buff1 == NULL) { lgerror(-ENOMEM, "Allocation error"); return -ENOMEM; } - - NETBUF_ALLOC(buff2, MNL_SOCKET_BUFFER_SIZE); - if (!NETBUF_CHECK(buff2)) { + size_t buff2_size = pktlen; + uint8_t *buff2 = malloc(buff2_size); + if (buff2 == NULL) { lgerror(-ENOMEM, "Allocation error"); - NETBUF_FREE(buff1); + free(buff1); return -ENOMEM; } - size_t buff1_size = MNL_SOCKET_BUFFER_SIZE; - size_t buff2_size = MNL_SOCKET_BUFFER_SIZE; - if ((ret = tcp_frag(pkt, pktlen, AVAILABLE_MTU-128, buff1, &buff1_size, buff2, &buff2_size)) < 0) { - errno = -ret; - goto free_buffs; + goto erret_lc; } int sent = 0; - int status = send_raw_socket(buff1, buff1_size); + ret = send_raw_socket(buff1, buff1_size); - if (status >= 0) sent += status; + if (ret >= 0) sent += ret; else { - ret = status; - goto free_buffs; + goto erret_lc; } - status = send_raw_socket(buff2, buff2_size); - if (status >= 0) sent += status; + ret = send_raw_socket(buff2, buff2_size); + if (ret >= 0) sent += ret; else { - ret = status; - goto free_buffs; + goto erret_lc; } - ret = sent; - -free_buffs: - NETBUF_FREE(buff1) - NETBUF_FREE(buff2) + free(buff1); + free(buff2); + return sent; +erret_lc: + free(buff1); + free(buff2); return ret; } @@ -555,7 +551,7 @@ free_buffs: } else if (ipvx == IP6VERSION) { ret = send_raw_ipv6(pkt, pktlen); } else { - lginfo("proto version %d is unsupported", ipvx); + printf("proto version %d is unsupported\n", ipvx); return -EINVAL; } @@ -563,6 +559,7 @@ free_buffs: return ret; } + // Per-queue data. Passed to queue_cb. struct queue_data { struct mnl_socket **_nl; @@ -725,12 +722,11 @@ int init_queue(int queue_num) { uint32_t portid = mnl_socket_get_portid(nl); struct nlmsghdr *nlh; - NETBUF_ALLOC(bbuf, BUF_SIZE); - if (!NETBUF_CHECK(bbuf)) { + char *buf = malloc(BUF_SIZE); + if (buf == NULL) { lgerror(-ENOMEM, "Allocation error"); goto die_alloc; } - char *buf = (char *)bbuf; /* Support for kernels versions < 3.8 */ // Obsolete and ignored in kernel version 3.8 @@ -837,12 +833,12 @@ int init_queue(int queue_num) { } - NETBUF_FREE(bbuf) + free(buf); close_socket(&nl); return 0; die: - NETBUF_FREE(bbuf) + free(buf); die_alloc: close_socket(&nl); return -1;