Add synfake option

This commit is contained in:
Vadim Vetrov 2024-08-29 14:45:27 +03:00
parent 33b0ca421b
commit 0f71d5f3c4
No known key found for this signature in database
GPG Key ID: E8A308689D7A73A5
4 changed files with 52 additions and 2 deletions

View File

@ -173,6 +173,8 @@ Available flags:
- `--fk-winsize=<winsize>` Specifies window size for the fragmented TCP packet. Applicable if you want for response to be fragmented. May slowdown connection initialization. - `--fk-winsize=<winsize>` Specifies window size for the fragmented TCP packet. Applicable if you want for response to be fragmented. May slowdown connection initialization.
- `--synfake={1|0}` If 1, syn payload will be sent before each request. The idea is taken from syndata from zapret project. Syn payload will normally be discarded by endpoint but may be handled by TSPU. This option sends normal fake in that payload. Please note, that the option works for all the sites, so --sni-domains won't change anything.
- `--sni-detection={parse|brute}` Specifies how to detect SNI. Parse will normally detect it by parsing the Client Hello message. Brute will go through the entire message and check possibility of SNI occurrence. Please note, that when `--sni-domains` option is not all brute will be O(nm) time complexity where n stands for length of the message and m is number of domains. Defaults to parse. - `--sni-detection={parse|brute}` Specifies how to detect SNI. Parse will normally detect it by parsing the Client Hello message. Brute will go through the entire message and check possibility of SNI occurrence. Please note, that when `--sni-domains` option is not all brute will be O(nm) time complexity where n stands for length of the message and m is number of domains. Defaults to parse.
- `--seg2delay=<delay>` This flag forces **youtubeUnblock** to wait a little bit before send the 2nd part of the split packet. - `--seg2delay=<delay>` This flag forces **youtubeUnblock** to wait a little bit before send the 2nd part of the split packet.

20
args.c
View File

@ -23,6 +23,7 @@ struct config_t config = {
.use_ipv6 = 1, .use_ipv6 = 1,
.fakeseq_offset = 10000, .fakeseq_offset = 10000,
.mark = DEFAULT_RAWSOCKET_MARK, .mark = DEFAULT_RAWSOCKET_MARK,
.synfake = 0,
.sni_detection = SNI_DETECTION_PARSE, .sni_detection = SNI_DETECTION_PARSE,
@ -69,19 +70,21 @@ struct config_t config = {
#define OPT_NO_IPV6 20 #define OPT_NO_IPV6 20
#define OPT_FAKE_SEQ_OFFSET 21 #define OPT_FAKE_SEQ_OFFSET 21
#define OPT_PACKET_MARK 22 #define OPT_PACKET_MARK 22
#define OPT_SYNFAKE 23
#define OPT_SEG2DELAY 5 #define OPT_SEG2DELAY 5
#define OPT_THREADS 6 #define OPT_THREADS 6
#define OPT_SILENT 7 #define OPT_SILENT 7
#define OPT_NO_GSO 8 #define OPT_NO_GSO 8
#define OPT_QUEUE_NUM 9 #define OPT_QUEUE_NUM 9
#define OPT_MAX OPT_PACKET_MARK #define OPT_MAX OPT_SYNFAKE
static struct option long_opt[] = { static struct option long_opt[] = {
{"help", 0, 0, 'h'}, {"help", 0, 0, 'h'},
{"version", 0, 0, 'v'}, {"version", 0, 0, 'v'},
{"sni-domains", 1, 0, OPT_SNI_DOMAINS}, {"sni-domains", 1, 0, OPT_SNI_DOMAINS},
{"fake-sni", 1, 0, OPT_FAKE_SNI}, {"fake-sni", 1, 0, OPT_FAKE_SNI},
{"synfake", 1, 0, OPT_SYNFAKE},
{"fake-sni-seq-len", 1, 0, OPT_FAKE_SNI_SEQ_LEN}, {"fake-sni-seq-len", 1, 0, OPT_FAKE_SNI_SEQ_LEN},
{"faking-strategy", 1, 0, OPT_FAKING_STRATEGY}, {"faking-strategy", 1, 0, OPT_FAKING_STRATEGY},
{"fake-seq-offset", 1, 0, OPT_FAKE_SEQ_OFFSET}, {"fake-seq-offset", 1, 0, OPT_FAKE_SEQ_OFFSET},
@ -141,6 +144,7 @@ void print_usage(const char *argv0) {
printf("\t--fake-seq-offset=<offset>\n"); printf("\t--fake-seq-offset=<offset>\n");
printf("\t--faking-ttl=<ttl>\n"); printf("\t--faking-ttl=<ttl>\n");
printf("\t--faking-strategy={randseq|ttl|tcp_check|pastseq}\n"); printf("\t--faking-strategy={randseq|ttl|tcp_check|pastseq}\n");
printf("\t--synfake={1|0}\n");
printf("\t--frag={tcp,ip,none}\n"); printf("\t--frag={tcp,ip,none}\n");
printf("\t--frag-sni-reverse={0|1}\n"); printf("\t--frag-sni-reverse={0|1}\n");
printf("\t--frag-sni-faked={0|1}\n"); printf("\t--frag-sni-faked={0|1}\n");
@ -310,6 +314,16 @@ int parse_args(int argc, char *argv[]) {
} }
config.fk_winsize = num; config.fk_winsize = num;
break;
case OPT_SYNFAKE:
if (strcmp(optarg, "1") == 0) {
config.synfake = 1;
} else if (strcmp(optarg, "0") == 0) {
config.synfake = 0;
} else {
goto invalid_opt;
}
break; break;
case OPT_SEG2DELAY: case OPT_SEG2DELAY:
num = parse_numeric_option(optarg); num = parse_numeric_option(optarg);
@ -420,6 +434,10 @@ void print_welcome() {
printf("Response TCP window will be set to %d with the appropriate scale\n", config.fk_winsize); printf("Response TCP window will be set to %d with the appropriate scale\n", config.fk_winsize);
} }
if (config.synfake) {
printf("Fake SYN payload will be sent with each TCP request SYN packet\n");
}
if (config.use_gso) { if (config.use_gso) {
printf("GSO is enabled\n"); printf("GSO is enabled\n");

View File

@ -46,6 +46,7 @@ struct config_t {
unsigned int fk_winsize; unsigned int fk_winsize;
unsigned int fakeseq_offset; unsigned int fakeseq_offset;
unsigned int mark; unsigned int mark;
int synfake;
}; };
extern struct config_t config; extern struct config_t config;

View File

@ -67,6 +67,8 @@ drop:
} }
int process_tcp_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 void *ipxh;
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;
@ -78,7 +80,7 @@ int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
lgtrace_addp("IPv%d", ipxv); lgtrace_addp("IPv%d", ipxv);
int ret = tcp_payload_split((uint8_t *)raw_payload, raw_payload_len, int ret = tcp_payload_split((uint8_t *)raw_payload, raw_payload_len,
NULL, NULL, (void *)&ipxh, &iph_len,
(struct tcphdr **)&tcph, &tcph_len, (struct tcphdr **)&tcph, &tcph_len,
(uint8_t **)&data, &dlen); (uint8_t **)&data, &dlen);
@ -87,6 +89,33 @@ int process_tcp_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
goto accept; goto accept;
} }
if (tcph->syn && config.synfake) {
lgtrace_addp("TCP syn alter");
uint8_t payload[MAX_PACKET_SIZE];
memcpy(payload, ipxh, iph_len);
memcpy(payload + iph_len, tcph, tcph_len);
memcpy(payload + iph_len + tcph_len, config.fake_sni_pkt, config.fake_sni_pkt_sz);
struct tcphdr *tcph = (struct tcphdr *)(payload + iph_len);
if (ipxv == IP4VERSION) {
struct iphdr *iph = (struct iphdr *)payload;
iph->tot_len = htons(iph_len + tcph_len + config.fake_sni_pkt_sz);
set_ip_checksum(payload, iph_len);
set_tcp_checksum(tcph, iph, iph_len);
} else if (ipxv == IP6VERSION) {
struct ip6_hdr *ip6h = (struct ip6_hdr *)payload;
ip6h->ip6_ctlun.ip6_un1.ip6_un1_plen = ntohs(tcph_len + config.fake_sni_pkt_sz);
set_ip_checksum(ip6h, iph_len);
set_tcp_checksum(tcph, ip6h, iph_len);
}
instance_config.send_raw_packet(payload, iph_len + tcph_len + config.fake_sni_pkt_sz);
goto drop;
}
struct tls_verdict vrd = analyze_tls_data(data, dlen); struct tls_verdict vrd = analyze_tls_data(data, dlen);
if (vrd.target_sni) { if (vrd.target_sni) {