Add Timestamp faking strategy

This commit is contained in:
Vadim Vetrov
2026-01-31 14:54:51 +03:00
parent da650bd09f
commit c9b59f9ce7
8 changed files with 295 additions and 114 deletions

View File

@@ -198,6 +198,11 @@ It should return low speed without **youtubeUnblock** and faster with it. With *
curl -o/dev/null -k --connect-to ::google.com -k -L -H Host:\ mirror.gcr.io https://mirror.gcr.io/v2/cimg/android/blobs/sha256:6fd8bdac3da660bde7bd0b6f2b6a46e1b686afb74b9a4614def32532b73f5eaa curl -o/dev/null -k --connect-to ::google.com -k -L -H Host:\ mirror.gcr.io https://mirror.gcr.io/v2/cimg/android/blobs/sha256:6fd8bdac3da660bde7bd0b6f2b6a46e1b686afb74b9a4614def32532b73f5eaa
``` ```
For ECH check it comes out to be more complicated, since it is still an experimental feature in CURL. If you want to test it, first of all, you should compile curl with ECH support. You can follow [this guide](https://github.com/curl/curl/blob/master/docs/ECH.md). Next, you can check it with
```sh
LD_LIBRARY_PATH=$HOME/code/openssl $HOME/code/curl/src/curl --ech hard --doh-url https://one.one.one.one/dns-query https://www.opengl.org --ipv4
```
## Flags ## Flags
Put flags to the **BINARY**, not an init script. If you are on OpenWRT you should put the flags inside the script: open `/etc/init.d/youtubeUnblock` with any text editor, like vi or nano and put your flags after `procd_set_param command /usr/bin/youtubeUnblock` line. Put flags to the **BINARY**, not an init script. If you are on OpenWRT you should put the flags inside the script: open `/etc/init.d/youtubeUnblock` with any text editor, like vi or nano and put your flags after `procd_set_param command /usr/bin/youtubeUnblock` line.
@@ -248,17 +253,20 @@ Flags that do not scoped to a specific section, used over all the youtubeUnblock
- `--fake-custom-payload-file=<binary file containing TLS message>` Same as `--fake-custom-payload` but binary file instead of hex. The file should contain raw binary TLS message (TCP payload). - `--fake-custom-payload-file=<binary file containing TLS message>` Same as `--fake-custom-payload` but binary file instead of hex. The file should contain raw binary TLS message (TCP payload).
- `--faking-strategy={randseq|ttl|tcp_check|pastseq|md5sum}` This flag determines the strategy of fake packets invalidation. Defaults to `randseq` - `--faking-strategy={randseq|ttl|tcp_check|pastseq|md5sum|timestamp}` This flag determines the strategy of fake packets invalidation. The user can specify multiple faking options, so multiple techniques will be applied to the fake packet. Defaults to `tcp_check,timestamp`.
- `randseq` specifies that random sequence/acknowledgment random will be set. This option may be handled by provider which uses *conntrack* with drop on invalid *conntrack* state firewall rule enabled. - `randseq` specifies that random sequence/acknowledgment random will be set. This option may be handled by provider which uses *conntrack* with drop on invalid *conntrack* state firewall rule enabled.
- `ttl` specifies that packet will be invalidated after `--faking-ttl=n` hops. `ttl` is better but may cause issues if unconfigured. - `ttl` specifies that packet will be invalidated after `--faking-ttl=n` hops. `ttl` is better but may cause issues if unconfigured.
- `pastseq` is like `randseq` but sequence number is not random but references the packet sent in the past (before current). - `pastseq` is like `randseq` but sequence number is not random but references the packet sent in the past (before current).
- `tcp_check` will invalidate faking packet with invalid checksum. May be handled and dropped by some providers/TSPUs. - `tcp_check` will invalidate faking packet with invalid checksum. May be handled and dropped by some providers/TSPUs.
- `md5sum` will invalidate faking packet with invalid TCP md5sum. md5sum is a TCP option which is handled by the destination server but may be skipped by TSPU. - `md5sum` will invalidate faking packet with invalid TCP md5sum. md5sum is a TCP option which is handled by the destination server but may be skipped by TSPU.
- `timestamp` utilizes TCP Timestamp option. Timestamp TSVal is decreased by `--faking-timestamp-decrease=n` parameter, so it is being rejected by the server.
- `--faking-ttl=<ttl>` Tunes the time to live (TTL) of fake SNI messages. TTL is specified like that the packet will go through the DPI system and captured by it, but will not reach the destination server. Defaults to **8**. - `--faking-ttl=<ttl>` Tunes the time to live (TTL) of fake SNI messages. TTL is specified like that the packet will go through the DPI system and captured by it, but will not reach the destination server. Defaults to **8**.
- `--fake-seq-offset` Tunes the offset from original sequence number for fake packets. Used by randseq faking strategy. Defaults to 10000. If 0, random sequence number will be set. - `--fake-seq-offset` Tunes the offset from original sequence number for fake packets. Used by randseq faking strategy. Defaults to 10000. If 0, random sequence number will be set.
- `--faking-timestamp-decrease=<val>` Decreases TSVal parameter of Timestamp option in fake packet by this value. The default is 600000. According to research made in zapret project, this parameter may work in range between 100 and 0x80000000.
- `--frag={tcp,ip,none}` Specifies the fragmentation strategy for the packet. tcp is used by default. Ip fragmentation may be blocked by DPI system. None specifies no fragmentation. Probably this won't work, but may be will work for some fake sni strategies. - `--frag={tcp,ip,none}` Specifies the fragmentation strategy for the packet. tcp is used by default. Ip fragmentation may be blocked by DPI system. None specifies no fragmentation. Probably this won't work, but may be will work for some fake sni strategies.
- `--frag-sni-reverse={0|1}` Specifies **youtubeUnblock** to send *ClientHello* fragments in the reverse order. Defaults to **1**. - `--frag-sni-reverse={0|1}` Specifies **youtubeUnblock** to send *ClientHello* fragments in the reverse order. Defaults to **1**.

View File

@@ -159,6 +159,62 @@ static long parse_numeric_option(const char* value) {
return result; return result;
} }
static int parse_faking_strategy(char *optarg, int *faking_strategy) {
*faking_strategy = 0;
char *p = optarg;
char *ep = p;
while (1) {
if (*ep == '\0' || *ep == ',') {
if (ep == p) {
if (*ep == '\0')
break;
p++, ep++;
continue;
}
char ep_endsym = *ep;
*ep = '\0';
if (strcmp(p, "randseq") == 0) {
*faking_strategy |= FAKE_STRAT_RAND_SEQ;
} else if (strcmp(p, "ttl") == 0) {
*faking_strategy |= FAKE_STRAT_TTL;
} else if (strcmp(p, "tcp_check") == 0) {
*faking_strategy |= FAKE_STRAT_TCP_CHECK;
} else if (strcmp(p, "pastseq") == 0) {
*faking_strategy |= FAKE_STRAT_PAST_SEQ;
} else if (strcmp(p, "md5sum") == 0) {
*faking_strategy |= FAKE_STRAT_TCP_MD5SUM;
} else if (strcmp(p, "timestamp") == 0) {
*faking_strategy |= FAKE_STRAT_TCP_TS;
} else {
return -1;
}
*ep = ep_endsym;
if (*ep == '\0') {
break;
} else {
p = ep + 1;
ep = p;
}
} else {
ep++;
}
}
if ( CHECK_BITFIELD(*faking_strategy, FAKE_STRAT_PAST_SEQ) &&
CHECK_BITFIELD(*faking_strategy, FAKE_STRAT_RAND_SEQ)) {
lgerr("Strategies pastseq and randseq are incompatible\n");
return -1;
}
return 0;
}
static int parse_udp_dport_range(char *str, struct udp_dport_range **udpr, int *udpr_len) { static int parse_udp_dport_range(char *str, struct udp_dport_range **udpr, int *udpr_len) {
int seclen = 1; int seclen = 1;
const char *p = str; const char *p = str;
@@ -297,6 +353,7 @@ enum {
OPT_FAKE_SNI, OPT_FAKE_SNI,
OPT_FAKING_TTL, OPT_FAKING_TTL,
OPT_FAKING_STRATEGY, OPT_FAKING_STRATEGY,
OPT_FAKING_TIMESTAMP_DECREASE,
OPT_FAKE_SNI_SEQ_LEN, OPT_FAKE_SNI_SEQ_LEN,
OPT_FAKE_SNI_TYPE, OPT_FAKE_SNI_TYPE,
OPT_FAKE_CUSTOM_PAYLOAD, OPT_FAKE_CUSTOM_PAYLOAD,
@@ -360,6 +417,7 @@ static struct option long_opt[] = {
{"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},
{"faking-ttl", 1, 0, OPT_FAKING_TTL}, {"faking-ttl", 1, 0, OPT_FAKING_TTL},
{"faking-timestamp-decrease", 1, 0, OPT_FAKING_TIMESTAMP_DECREASE},
{"frag", 1, 0, OPT_FRAG}, {"frag", 1, 0, OPT_FRAG},
{"frag-sni-reverse", 1, 0, OPT_FRAG_SNI_REVERSE}, {"frag-sni-reverse", 1, 0, OPT_FRAG_SNI_REVERSE},
{"frag-sni-faked", 1, 0, OPT_FRAG_SNI_FAKED}, {"frag-sni-faked", 1, 0, OPT_FRAG_SNI_FAKED},
@@ -425,7 +483,8 @@ void print_usage(const char *argv0) {
printf("\t--fake-custom-payload-file=<binary file containing TLS message>\n"); printf("\t--fake-custom-payload-file=<binary file containing TLS message>\n");
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|md5sum}\n"); printf("\t--faking-timestamp-decrease=<val>\n");
printf("\t--faking-strategy={randseq|ttl|tcp_check|pastseq|md5sum|timestamp}\n");
printf("\t--synfake={1|0}\n"); printf("\t--synfake={1|0}\n");
printf("\t--synfake-len=<len>\n"); printf("\t--synfake-len=<len>\n");
printf("\t--frag={tcp,ip,none}\n"); printf("\t--frag={tcp,ip,none}\n");
@@ -730,21 +789,11 @@ int yparse_args(struct config_t *config, int argc, char *argv[]) {
sect_config->frag_sni_pos = num; sect_config->frag_sni_pos = num;
break; break;
case OPT_FAKING_STRATEGY: case OPT_FAKING_STRATEGY:
if (strcmp(optarg, "randseq") == 0) { if (parse_faking_strategy(
sect_config->faking_strategy = FAKE_STRAT_RAND_SEQ; optarg, &sect_config->faking_strategy) < 0) {
} else if (strcmp(optarg, "ttl") == 0) {
sect_config->faking_strategy = FAKE_STRAT_TTL;
} else if (strcmp(optarg, "tcp_check") == 0) {
sect_config->faking_strategy = FAKE_STRAT_TCP_CHECK;
} else if (strcmp(optarg, "pastseq") == 0) {
sect_config->faking_strategy = FAKE_STRAT_PAST_SEQ;
} else if (strcmp(optarg, "md5sum") == 0) {
sect_config->faking_strategy = FAKE_STRAT_TCP_MD5SUM;
} else {
goto invalid_opt; goto invalid_opt;
} }
break;
break;
case OPT_FAKING_TTL: case OPT_FAKING_TTL:
num = parse_numeric_option(optarg); num = parse_numeric_option(optarg);
if (errno != 0 || num < 0 || num > 255) { if (errno != 0 || num < 0 || num > 255) {
@@ -753,6 +802,14 @@ int yparse_args(struct config_t *config, int argc, char *argv[]) {
sect_config->faking_ttl = num; sect_config->faking_ttl = num;
break; break;
case OPT_FAKING_TIMESTAMP_DECREASE:
num = parse_numeric_option(optarg);
if (errno != 0) {
goto invalid_opt;
}
sect_config->faking_timestamp_decrease = num;
break;
case OPT_FAKE_SEQ_OFFSET: case OPT_FAKE_SEQ_OFFSET:
num = parse_numeric_option(optarg); num = parse_numeric_option(optarg);
if (errno != 0) { if (errno != 0) {
@@ -1033,33 +1090,66 @@ static size_t print_config_section(const struct section_config_t *section, char
case FAKE_PAYLOAD_DEFAULT: case FAKE_PAYLOAD_DEFAULT:
print_cnf_buf("--fake-sni-type=default"); print_cnf_buf("--fake-sni-type=default");
break; break;
}
switch(section->faking_strategy) {
case FAKE_STRAT_TTL:
print_cnf_buf("--faking-strategy=ttl");
print_cnf_buf("--faking-ttl=%d", section->faking_ttl);
break;
case FAKE_STRAT_RAND_SEQ:
print_cnf_buf("--faking-strategy=randseq");
break;
case FAKE_STRAT_TCP_CHECK:
print_cnf_buf("--faking-strategy=tcp_check");
break;
case FAKE_STRAT_TCP_MD5SUM:
print_cnf_buf("--faking-strategy=md5sum");
break;
case FAKE_STRAT_PAST_SEQ:
print_cnf_buf("--faking-strategy=pastseq");
print_cnf_buf("--fake-seq-offset=%d", section->fakeseq_offset);
break;
} }
print_cnf_buf("--seg2delay=%d", section->seg2_delay); print_cnf_buf("--seg2delay=%d", section->seg2_delay);
} else { } else {
print_cnf_buf("--fake-sni=0"); print_cnf_buf("--fake-sni=0");
} }
if (section->fake_sni && section->faking_strategy) {
int show_ttl = 0;
int show_seq_offset = 0;
int show_faking_ts_decr = 0;
print_cnf_raw("--faking-strategy=");
if (CHECK_BITFIELD(section->faking_strategy, FAKE_STRAT_TTL)) {
print_cnf_raw("ttl");
print_cnf_raw(",");
show_ttl = 1;
}
if (CHECK_BITFIELD(section->faking_strategy, FAKE_STRAT_RAND_SEQ)) {
print_cnf_raw("randseq");
print_cnf_raw(",");
show_ttl = 1;
}
if (CHECK_BITFIELD(section->faking_strategy, FAKE_STRAT_TCP_CHECK)) {
print_cnf_raw("tcp_check");
print_cnf_raw(",");
}
if (CHECK_BITFIELD(section->faking_strategy, FAKE_STRAT_TCP_MD5SUM)) {
print_cnf_raw("md5sum");
print_cnf_raw(",");
}
if (CHECK_BITFIELD(section->faking_strategy, FAKE_STRAT_TCP_TS)) {
print_cnf_raw("timestamp");
print_cnf_raw(",");
show_faking_ts_decr = 1;
}
if (CHECK_BITFIELD(section->faking_strategy, FAKE_STRAT_PAST_SEQ)) {
print_cnf_raw("pastseq");
print_cnf_raw(",");
}
// delete comma and write space
print_cnf_raw("\b ");
if (show_ttl) {
print_cnf_buf("--faking-ttl=%d", section->faking_ttl);
}
if (show_seq_offset) {
print_cnf_buf("--fake-seq-offset=%d", section->fakeseq_offset);
}
if (show_faking_ts_decr) {
print_cnf_buf("--faking-timestamp-decrease=%d",
section->faking_timestamp_decrease);
}
}
} else { } else {
print_cnf_buf("--tls=disabled"); print_cnf_buf("--tls=disabled");
} }
@@ -1247,8 +1337,8 @@ int init_section_config(struct section_config_t **section, struct section_config
return ret; return ret;
} }
def_section->fake_sni_pkt = fake_sni_old; def_section->fake_sni_pkt = fake_sni;
def_section->fake_sni_pkt_sz = sizeof(fake_sni_old) - 1; def_section->fake_sni_pkt_sz = sizeof(fake_sni) - 1;
*section = def_section; *section = def_section;
return 0; return 0;

View File

@@ -71,6 +71,7 @@ struct section_config_t {
int frag_middle_sni; int frag_middle_sni;
int frag_sni_pos; int frag_sni_pos;
unsigned char faking_ttl; unsigned char faking_ttl;
unsigned int faking_timestamp_decrease;
int fake_sni; int fake_sni;
unsigned int fake_sni_seq_len; unsigned int fake_sni_seq_len;
@@ -176,6 +177,7 @@ for (struct section_config_t *section = (config)->last_section; section != NULL;
#endif #endif
#define FAKE_TTL 8 #define FAKE_TTL 8
#define FAKING_TIMESTAMP_DECREASE_TTL 600000
#define FAKE_STRAT_NONE 0 #define FAKE_STRAT_NONE 0
// Will invalidate fake packets by out-of-ack_seq out-of-seq request // Will invalidate fake packets by out-of-ack_seq out-of-seq request
@@ -187,6 +189,7 @@ for (struct section_config_t *section = (config)->last_section; section != NULL;
#define FAKE_STRAT_TCP_CHECK (1 << 3) #define FAKE_STRAT_TCP_CHECK (1 << 3)
#define FAKE_STRAT_TCP_MD5SUM (1 << 4) #define FAKE_STRAT_TCP_MD5SUM (1 << 4)
#define FAKE_STRAT_UDP_CHECK (1 << 5) #define FAKE_STRAT_UDP_CHECK (1 << 5)
#define FAKE_STRAT_TCP_TS (1 << 6)
#define FAKE_STRAT_COUNT 6 #define FAKE_STRAT_COUNT 6
@@ -199,7 +202,7 @@ for (int strategy = 1; strategy <= (1 << FAKE_STRAT_COUNT); strategy <<= 1) \
if ((fake_bitmask) & strategy) if ((fake_bitmask) & strategy)
#ifndef FAKING_STRATEGY #ifndef FAKING_STRATEGY
#define FAKING_STRATEGY FAKE_STRAT_PAST_SEQ #define FAKING_STRATEGY FAKE_STRAT_TCP_CHECK | FAKE_STRAT_TCP_TS
#endif #endif
#define MAX_FAKE_SIZE 1300 #define MAX_FAKE_SIZE 1300
@@ -241,7 +244,8 @@ enum {
.fragmentation_strategy = FRAGMENTATION_STRATEGY, \ .fragmentation_strategy = FRAGMENTATION_STRATEGY, \
.faking_strategy = FAKING_STRATEGY, \ .faking_strategy = FAKING_STRATEGY, \
.faking_ttl = FAKE_TTL, \ .faking_ttl = FAKE_TTL, \
.fake_sni = 0, \ .faking_timestamp_decrease = FAKING_TIMESTAMP_DECREASE_TTL, \
.fake_sni = 1, \
.fake_sni_seq_len = 1, \ .fake_sni_seq_len = 1, \
.fake_sni_type = FAKE_PAYLOAD_DEFAULT, \ .fake_sni_type = FAKE_PAYLOAD_DEFAULT, \
.fake_custom_pkt = NULL, \ .fake_custom_pkt = NULL, \

View File

@@ -315,7 +315,6 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
set_tcp_checksum(tcph, iph, iph_len); set_tcp_checksum(tcph, iph, iph_len);
} }
/*
if (0) { if (0) {
int delta = 2; int delta = 2;
ret = seqovl_packet(payload, &payload_len, delta); ret = seqovl_packet(payload, &payload_len, delta);
@@ -326,14 +325,28 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
lgerror(ret, "seqovl_packet delta %d", delta); lgerror(ret, "seqovl_packet delta %d", delta);
} }
} }
*/
if (dlen > AVAILABLE_MTU) { if (dlen > AVAILABLE_MTU) {
lgdebug("WARNING! Client Hello packet is too big and may cause issues!"); lgdebug("WARNING! Client Hello packet is too big and may cause issues!");
} }
if (section->fake_sni) { if (section->fake_sni) {
post_fake_sni(args_default_fake_type(section), iph, iph_len, tcph, tcph_len); struct fake_type f_type = args_default_fake_type(section);
// f_type.strategy.strategy = FAKE_STRAT_RAND_SEQ;
// f_type.strategy.randseq_offset = f_type.fake_len - 1;
// f_type.fake_data = "\x16";
// f_type.fake_len = 1;
//
// post_fake_sni(f_type, iph, iph_len, tcph, tcph_len);
//
// f_type = args_default_fake_type(section);
// // f_type.strategy.strategy = FAKE_STRAT_RAND_SEQ;
// // f_type.strategy.randseq_offset = 0;
// f_type.fake_data += 1;
// f_type.fake_len -= 1;
post_fake_sni(f_type, iph, iph_len, tcph, tcph_len);
} }
size_t ipd_offset; size_t ipd_offset;
@@ -653,6 +666,7 @@ send_fake:
struct tcphdr *tcph; struct tcphdr *tcph;
ret = tcp_payload_split(frag2, f2len, &iph, &iphfl, &tcph, &tcphfl, NULL, NULL); ret = tcp_payload_split(frag2, f2len, &iph, &iphfl, &tcph, &tcphfl, NULL, NULL);
struct fake_type f_type = args_default_fake_type(section); struct fake_type f_type = args_default_fake_type(section);
if ((f_type.strategy.strategy & FAKE_STRAT_PAST_SEQ) == FAKE_STRAT_PAST_SEQ) { if ((f_type.strategy.strategy & FAKE_STRAT_PAST_SEQ) == FAKE_STRAT_PAST_SEQ) {
f_type.strategy.strategy ^= FAKE_STRAT_PAST_SEQ; f_type.strategy.strategy ^= FAKE_STRAT_PAST_SEQ;
f_type.strategy.strategy |= FAKE_STRAT_RAND_SEQ; f_type.strategy.strategy |= FAKE_STRAT_RAND_SEQ;
@@ -704,71 +718,68 @@ int post_fake_sni(struct fake_type f_type,
void *fsiph = (void *)rfsiph; void *fsiph = (void *)rfsiph;
struct tcphdr *fstcph = (void *)rfstcph; struct tcphdr *fstcph = (void *)rfstcph;
ITER_FAKE_STRAT(f_type.strategy.strategy, strategy) { struct fake_type fake_seq_type = f_type;
struct fake_type fake_seq_type = f_type;
fake_seq_type.strategy.strategy = strategy;
// one goes for default fake // one goes for default fake
for (int i = 0; i < fake_seq_type.sequence_len; i++) { for (int i = 0; i < fake_seq_type.sequence_len; i++) {
uint8_t *fake_sni; uint8_t *fake_sni;
size_t fake_sni_len; size_t fake_sni_len;
ret = gen_fake_sni( ret = gen_fake_sni(
fake_seq_type, fake_seq_type,
fsiph, iph_len, fstcph, tcph_len, fsiph, iph_len, fstcph, tcph_len,
&fake_sni, &fake_sni_len); &fake_sni, &fake_sni_len);
if (ret < 0) { if (ret < 0) {
lgerror(ret, "gen_fake_sni"); lgerror(ret, "gen_fake_sni");
return ret;
}
lgtrace_addp("post fake sni #%d", i + 1);
if (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, fake_sni_len);
}
if (ret < 0) {
lgerror(ret, "send fake sni");
goto erret_lc;
}
size_t iph_len;
size_t tcph_len;
size_t plen;
ret = tcp_payload_split(
fake_sni, fake_sni_len,
&fsiph, &iph_len,
&fstcph, &tcph_len,
NULL, &plen);
if (ret < 0) {
lgtrace_addp("continue fake seq");
goto erret_lc;
}
if (!(strategy == FAKE_STRAT_PAST_SEQ ||
strategy == FAKE_STRAT_RAND_SEQ)) {
fstcph->seq = htonl(ntohl(fstcph->seq) + plen);
}
if (ipxv == IP4VERSION) {
((struct iphdr *)fsiph)->id = htons(ntohs(((struct iphdr *)fsiph)->id) + 1);
}
memcpy(rfsiph, fsiph, iph_len);
memcpy(rfstcph, fstcph, tcph_len);
fsiph = (void *)rfsiph;
fstcph = (void *)rfstcph;
free(fake_sni);
continue;
erret_lc:
free(fake_sni);
return ret; return ret;
} }
lgtrace_addp("post fake sni #%d", i + 1);
if (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, fake_sni_len);
}
if (ret < 0) {
lgerror(ret, "send fake sni");
goto erret_lc;
}
size_t iph_len;
size_t tcph_len;
size_t plen;
ret = tcp_payload_split(
fake_sni, fake_sni_len,
&fsiph, &iph_len,
&fstcph, &tcph_len,
NULL, &plen);
if (ret < 0) {
lgtrace_addp("continue fake seq");
goto erret_lc;
}
if (!(CHECK_BITFIELD(f_type.strategy.strategy, FAKE_STRAT_PAST_SEQ) ||
CHECK_BITFIELD(f_type.strategy.strategy, FAKE_STRAT_RAND_SEQ))) {
fstcph->seq = htonl(ntohl(fstcph->seq) + plen);
}
if (ipxv == IP4VERSION) {
((struct iphdr *)fsiph)->id = htons(ntohs(((struct iphdr *)fsiph)->id) + 1);
}
memcpy(rfsiph, fsiph, iph_len);
memcpy(rfstcph, fstcph, tcph_len);
fsiph = (void *)rfsiph;
fstcph = (void *)rfstcph;
free(fake_sni);
continue;
erret_lc:
free(fake_sni);
return ret;
} }
return 0; return 0;

View File

@@ -5,6 +5,5 @@
static const char fake_sni[] = "\026\003\001\002\000\001\000\001\374\003\003\323[\345\201f\362\200:B\356Uq\355X\315i\235*\021\367\331\272\a>\233\254\355\307/\342\372\265 \275\2459l&r\222\313\361\3729`\376\256\233\333O\001\373\33050\r\260f,\231\035 \324^\000>\023\002\023\003\023\001\300,\3000\000\237\314\251\314\250\314\252\300+\300/\000\236\300$\300(\000k\300#\300'\000g\300\n\300\024\0009\300\t\300\023\0003\000\235\000\234\000=\000<\0005\000/\000\377\001\000\001u\000\000\000\023\000\021\000\000\016www.google.com\000\v\000\004\003\000\001\002\000\n\000\026\000\024\000\035\000\027\000\036\000\031\000\030\001\000\001\001\001\002\001\003\001\004\000\020\000\016\000\f\002h2\bhttp/1.1\000\026\000\000\000\027\000\000\0001\000\000\000\r\0000\000.\004\003\005\003\006\003\b\a\b\b\b\032\b\033\b\034\b\t\b\n\b\v\b\004\b\005\b\006\004\001\005\001\006\001\003\003\003\001\003\002\004\002\005\002\006\002\000+\000\005\004\003\004\003\003\000-\000\002\001\001\0003\000&\000$\000\035\000 \004\224\206\021\256\f\222\266\3435\216\202\342\2573\341\3503\2107\341\023\016\240r|6\000^K\310s\000\025\000\255\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; static const char fake_sni[] = "\026\003\001\002\000\001\000\001\374\003\003\323[\345\201f\362\200:B\356Uq\355X\315i\235*\021\367\331\272\a>\233\254\355\307/\342\372\265 \275\2459l&r\222\313\361\3729`\376\256\233\333O\001\373\33050\r\260f,\231\035 \324^\000>\023\002\023\003\023\001\300,\3000\000\237\314\251\314\250\314\252\300+\300/\000\236\300$\300(\000k\300#\300'\000g\300\n\300\024\0009\300\t\300\023\0003\000\235\000\234\000=\000<\0005\000/\000\377\001\000\001u\000\000\000\023\000\021\000\000\016www.google.com\000\v\000\004\003\000\001\002\000\n\000\026\000\024\000\035\000\027\000\036\000\031\000\030\001\000\001\001\001\002\001\003\001\004\000\020\000\016\000\f\002h2\bhttp/1.1\000\026\000\000\000\027\000\000\0001\000\000\000\r\0000\000.\004\003\005\003\006\003\b\a\b\b\b\032\b\033\b\034\b\t\b\n\b\v\b\004\b\005\b\006\004\001\005\001\006\001\003\003\003\001\003\002\004\002\005\002\006\002\000+\000\005\004\003\004\003\003\000-\000\002\001\001\0003\000&\000$\000\035\000 \004\224\206\021\256\f\222\266\3435\216\202\342\2573\341\3503\2107\341\023\016\240r|6\000^K\310s\000\025\000\255\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000";
static const char fake_sni_old[] = "\026\003\001\004\316\001\000\004\312\003\003K+\272\314\340\306\374>dw%\f\223\346\225\270\270~\335\027\f\264\341H\267\357\303\216T\322[\371 \245\320\212V6\374\3706\232\0216B\325\273P\b\300>\0332>\362\323\033\322\301\204\022f8\223\214\000\"\023\001\023\003\023\002\300+\300/\314\251\314\250\300,\3000\300\n\300\t\300\023\300\024\000\234\000\235\000/\0005\001\000\004_\000\000\000\023\000\021\000\000\016www.google.com\000\027\000\000\377\001\000\001\000\000\n\000\016\000\f\000\035\000\027\000\030\000\031\001\000\001\001\000\v\000\002\001\000\000\020\000\v\000\t\bhttp/1.1\000\005\000\005\001\000\000\000\000\000\"\000\n\000\b\004\003\005\003\006\003\002\003\0003\000k\000i\000\035\000 \333C\212\234-\t\237#\202\\\231\311\022]\333\341t(\t\276U\373u\234\316J~,^|*Z\000\027\000A\004k\n\255\254\376X\226t\001;n~\033\034.\245\027\024\3762_\352$\374\346^f\fF,\201\275\263\336O\231\001\032\200\357dI\266y\031\323\311vR\232\004\r\366FT\004\335\326\356\256\230B\t\313\000*\000\000\000+\000\005\004\003\004\003\003\000\r\000\030\000\026\004\003\005\003\006\003\b\004\b\005\b\006\004\001\005\001\006\001\002\003\002\001\000-\000\002\001\001\000\034\000\002@\001\376\r\0029\000\000\001\000\003\344\000 \337\306\243\332Y\033\a\252\352\025\365Z\035\223\226\304\255\363\215G\356g\344%}7\217\033n\211^\201\002\017g\267\334\326OD}\336\341ZC\230\226'\225\313\357\211\\\242\273\030k\216\377U\315\206\2410\200\203\332Z\223\005\370\b\304\370f\017\200\023\241\223~?\270{\037b\312\001\270\227\366\356\352\002\314\351\006\237\241q\226\300\314\321o\247{\201\317\230}B\005T\3660\335\320\332r?S\217\tq\036\031\326I|\237]\311 c\f\024r\031\310W\373\257\314q)q\030\237\261\227\217Kd?\257'G\320\020\340\256ND\247\005\341\324\024OP>\370\350\270b\311wAj\t\311\213\365i\203\230x\207\354\245<\274\202\230c\v0Y\263\364\022\303a\200\022\031\314\271rl=\327\336\001\327\264\267\342\353\352=\354[u\224\260\257\034\004\232\023\226}\227\030e\221\"\350\207\027dId\324\305\362N:\035\307`\204\337\201;\221\320\266b\362hrH\345e\206\246%\006\020a4\3430\036\225\215\274\275\360Q&\271\237)\222uK\362\017o\220\226W\357\267#\357\v\023\354\213\2629\331\ad\005/~6k\000[\247\301\270\310qJ\004\303|m5\363\376Y\002\243}6\251x\024\331)GH\335\205rI\032\f\210\a\212\347]\271\030\347.\021\213\365\026\030\340/Ny\r\332\3577\3203\026iX}>\2507\327&XRXU!\017\270I\313\352\350^?\352Uss\017\266pF\222NI\245\307_\305#\361\352\243+-\266\317Q\036s\243\277\355{S&\023>\275\360\215\032V\237XOY\345u>\002\305\252T\354\035\327v{P\352M\233\366\221\270\377\251\261f+rF\201wL2W\266X\252\242X\2536I\337c\205uZ\254Fe\305h\t\371\376\216r\336Y\327h\347*\331\257-ZQ{(\336\226\206\017\037\036\021\341\027z\033\254\235\252\227\224\004?p\243\351\\\263\352\205\327#W\345\255\256\375\267bP\3047\363!*K\003t\212(\306\214P\215\3506j\025\375\213e\254s\000)\001\034\000\367\000\361\002\276W%\232?\326\223\277\211v\017\a\361\347\312N\226\024L\260v\210\271j\324[|\270\344\3773\321-\313b>~\310\253XIR\324)&;\033{g;)\344\255\226\370\347I\\y\020\324\360\211vC\310\226s\267|\273$\341\332\2045qh\245w\2255\214\316\030\255\301\326C\343\304=\245\231h`yd\000#s\002\370\374Z\0336\245\361\226\222\306\032k\2457\016h\314(R;\326T~EHH\352\307\023^\247\363\321`V\340\253Z\233\357\227I\373\337z\177\nv\261\252\371\017\226\223\345\005\315y4\b\236N0\2630\017\215c\305&L\260\346J\237\203Q(\335W\027|>\3553\275j\307?W5\3463kc\350\262C\361 \037w!\371}\214\"I\377|\331@a;\342\3566\312\272Z\327u7\204'\215YBLL\235\236\242\345\215\245T\211a\312\263\342\000! \221\202X$\302\317\203\246\207c{\231\330\264\324\\k\271\272\336\356\002|\261O\207\030+\367P\317\356";
#endif /*RAW_REPLACEMENTS_H*/ #endif /*RAW_REPLACEMENTS_H*/

View File

@@ -111,6 +111,9 @@ free((item)); \
#ifndef KERNEL_SPACE #ifndef KERNEL_SPACE
#define CHECK_BITFIELD(value, field) (((value) & (field)) == (field))
#define max(a,b)__extension__\ #define max(a,b)__extension__\
({ \ ({ \
__typeof__ (a) _a = (a); \ __typeof__ (a) _a = (a); \

View File

@@ -616,6 +616,15 @@ struct tcp_md5sig_opt {
// Real length of the option, with NOOP fillers // Real length of the option, with NOOP fillers
#define TCP_MD5SIG_OPT_RLEN 20 #define TCP_MD5SIG_OPT_RLEN 20
#define TCP_TS_OPT_KIND 0x08
struct tcp_ts_opt {
uint8_t kind;
uint8_t len;
uint32_t ts_val;
uint32_t ts_echo;
} __attribute__((packed));
int fail_packet(struct failing_strategy strategy, uint8_t *payload, size_t *plen, size_t avail_buflen) { int fail_packet(struct failing_strategy strategy, uint8_t *payload, size_t *plen, size_t avail_buflen) {
void *iph; void *iph;
size_t iph_len; size_t iph_len;
@@ -636,18 +645,22 @@ int fail_packet(struct failing_strategy strategy, uint8_t *payload, size_t *plen
} }
if (strategy.strategy == FAKE_STRAT_RAND_SEQ) { if (CHECK_BITFIELD(strategy.strategy, FAKE_STRAT_RAND_SEQ)) {
lgtrace_wr("fake seq: %u -> ", ntohl(tcph->seq)); lgtrace_wr("fake seq: %u -> ", ntohl(tcph->seq));
tcph->seq = htonl(ntohl(tcph->seq) - (strategy.randseq_offset + dlen)); tcph->seq = htonl(ntohl(tcph->seq) - (strategy.randseq_offset + dlen));
lgtrace_addp("%u", ntohl(tcph->seq)); lgtrace_addp("%u", ntohl(tcph->seq));
} else if (strategy.strategy == FAKE_STRAT_PAST_SEQ) { }
if (CHECK_BITFIELD(strategy.strategy, FAKE_STRAT_PAST_SEQ)) {
lgtrace_wr("fake seq: %u -> ", ntohl(tcph->seq)); lgtrace_wr("fake seq: %u -> ", ntohl(tcph->seq));
tcph->seq = htonl(ntohl(tcph->seq) - dlen); tcph->seq = htonl(ntohl(tcph->seq) - dlen);
lgtrace_addp("%u", ntohl(tcph->seq)); lgtrace_addp("%u", ntohl(tcph->seq));
} else if (strategy.strategy == FAKE_STRAT_TTL) { }
if (CHECK_BITFIELD(strategy.strategy, FAKE_STRAT_TTL)) {
lgtrace_addp("set fake ttl to %d", strategy.faking_ttl); lgtrace_addp("set fake ttl to %d", strategy.faking_ttl);
if (ipxv == IP4VERSION) { if (ipxv == IP4VERSION) {
@@ -658,7 +671,9 @@ int fail_packet(struct failing_strategy strategy, uint8_t *payload, size_t *plen
lgerror(-EINVAL, "fail_packet: IP version is unsupported"); lgerror(-EINVAL, "fail_packet: IP version is unsupported");
return -EINVAL; return -EINVAL;
} }
} else if (strategy.strategy == FAKE_STRAT_TCP_MD5SUM) { }
if (CHECK_BITFIELD(strategy.strategy, FAKE_STRAT_TCP_MD5SUM)) {
int optp_len = tcph_len - sizeof(struct tcphdr); int optp_len = tcph_len - sizeof(struct tcphdr);
int delta = TCP_MD5SIG_OPT_RLEN - optp_len; int delta = TCP_MD5SIG_OPT_RLEN - optp_len;
lgtrace_addp("Incr delta %d: %d -> %d", delta, optp_len, optp_len + delta); lgtrace_addp("Incr delta %d: %d -> %d", delta, optp_len, optp_len + delta);
@@ -673,9 +688,11 @@ int fail_packet(struct failing_strategy strategy, uint8_t *payload, size_t *plen
tcph_len = tcph_len + delta; tcph_len = tcph_len + delta;
tcph->doff = tcph_len >> 2; tcph->doff = tcph_len >> 2;
if (ipxv == IP4VERSION) { if (ipxv == IP4VERSION) {
((struct iphdr *)iph)->tot_len = htons(ntohs(((struct iphdr *)iph)->tot_len) + delta); ((struct iphdr *)iph)->tot_len =
htons(ntohs(((struct iphdr *)iph)->tot_len) + delta);
} else if (ipxv == IP6VERSION) { } else if (ipxv == IP6VERSION) {
((struct ip6_hdr *)iph)->ip6_plen = htons(ntohs(((struct ip6_hdr *)iph)->ip6_plen) + delta); ((struct ip6_hdr *)iph)->ip6_plen =
htons(ntohs(((struct ip6_hdr *)iph)->ip6_plen) + delta);
} else { } else {
lgerror(-EINVAL, "fail_packet: IP version is unsupported"); lgerror(-EINVAL, "fail_packet: IP version is unsupported");
return -EINVAL; return -EINVAL;
@@ -697,6 +714,53 @@ int fail_packet(struct failing_strategy strategy, uint8_t *payload, size_t *plen
} }
} }
if (CHECK_BITFIELD(strategy.strategy, FAKE_STRAT_TCP_TS)) {
int optp_len = tcph_len - sizeof(struct tcphdr);
uint8_t *optp = (uint8_t *)tcph + sizeof(struct tcphdr);
uint8_t *tcp_ts = NULL;
while (optp_len && *optp != 0x00) {
if (*optp == 0x01) {
optp_len--;
optp++;
continue;
}
if (optp_len < 2) {
lgerr("Tcp option parsing failed");
break;
}
uint8_t len = optp[1];
if (len > optp_len) {
lgerr("Tcp option parsing failed");
break;
}
if (*optp == 0x08) {
tcp_ts = optp;
break;
}
optp_len -= len;
optp += len;
}
if (tcp_ts) {
struct tcp_ts_opt *ts_opt = (void *)tcp_ts;
uint32_t old_ts = ntohl(ts_opt->ts_val);
ts_opt->ts_val = htonl(ntohl(ts_opt->ts_val) -
strategy.faking_timestamp_decrease);
uint32_t new_ts = ntohl(ts_opt->ts_val);
lgtrace_addp( "Fake TCP TimeStamp %u -> %u", old_ts, new_ts);
} else {
lgtrace_addp( "Fake TCP TimeStamp was not fullfilled: "
"the option does not present");
}
}
if (ipxv == IP4VERSION) { if (ipxv == IP4VERSION) {
((struct iphdr *)iph)->frag_off = 0; ((struct iphdr *)iph)->frag_off = 0;
} }
@@ -705,7 +769,7 @@ int fail_packet(struct failing_strategy strategy, uint8_t *payload, size_t *plen
set_ip_checksum(iph, iph_len); set_ip_checksum(iph, iph_len);
set_tcp_checksum(tcph, iph, iph_len); set_tcp_checksum(tcph, iph, iph_len);
if (strategy.strategy == FAKE_STRAT_TCP_CHECK) { if (CHECK_BITFIELD(strategy.strategy, FAKE_STRAT_TCP_CHECK)) {
lgtrace_addp("break fake tcp checksum"); lgtrace_addp("break fake tcp checksum");
tcph->check += 1; tcph->check += 1;
} }

View File

@@ -133,6 +133,7 @@ void shift_data(uint8_t *data, size_t dlen, size_t delta);
struct failing_strategy { struct failing_strategy {
unsigned int strategy; unsigned int strategy;
uint8_t faking_ttl; uint8_t faking_ttl;
uint32_t faking_timestamp_decrease;
size_t randseq_offset; size_t randseq_offset;
}; };
@@ -197,7 +198,8 @@ static inline struct failing_strategy args_default_failing_strategy(const struct
struct failing_strategy fl_strat = { struct failing_strategy fl_strat = {
.strategy = (unsigned int)section->faking_strategy, .strategy = (unsigned int)section->faking_strategy,
.faking_ttl = section->faking_ttl, .faking_ttl = section->faking_ttl,
.randseq_offset = (size_t)section->fakeseq_offset .faking_timestamp_decrease = section->faking_timestamp_decrease,
.randseq_offset = (size_t)section->fakeseq_offset,
}; };
return fl_strat; return fl_strat;
} }