forked from Waujito/youtubeUnblock
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathargs.c
408 lines (355 loc) · 9.29 KB
/
args.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
#include "config.h"
#include "raw_replacements.h"
#include <stdbool.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
struct config_t config = {
.threads = THREADS_NUM,
.frag_sni_reverse = 1,
.frag_sni_faked = 0,
.fragmentation_strategy = FRAGMENTATION_STRATEGY,
.faking_strategy = FAKING_STRATEGY,
.faking_ttl = FAKE_TTL,
.fake_sni = 1,
.fake_sni_seq_len = 1,
.frag_middle_sni = 1,
.frag_sni_pos = 2,
.sni_detection = SNI_DETECTION_PARSE,
#ifdef SEG2_DELAY
.seg2_delay = SEG2_DELAY,
#else
.seg2_delay = 0,
#endif
#ifdef USE_GSO
.use_gso = true,
#else
.use_gso = false,
#endif
#ifdef DEBUG
.verbose = 1,
#else
.verbose = 0,
#endif
.domains_str = defaul_snistr,
.domains_strlen = sizeof(defaul_snistr),
.queue_start_num = DEFAULT_QUEUE_NUM,
.fake_sni_pkt = fake_sni_old,
.fake_sni_pkt_sz = sizeof(fake_sni_old) - 1, // - 1 for null-terminator
};
#define OPT_SNI_DOMAINS 1
#define OPT_FAKE_SNI 2
#define OPT_FAKING_TTL 3
#define OPT_FAKING_STRATEGY 10
#define OPT_FAKE_SNI_SEQ_LEN 11
#define OPT_FRAG 4
#define OPT_FRAG_SNI_REVERSE 12
#define OPT_FRAG_SNI_FAKED 13
#define OPT_FRAG_MIDDLE_SNI 18
#define OPT_FRAG_SNI_POS 19
#define OPT_FK_WINSIZE 14
#define OPT_TRACE 15
#define OPT_QUIC_DROP 16
#define OPT_SNI_DETECTION 17
#define OPT_SEG2DELAY 5
#define OPT_THREADS 6
#define OPT_SILENT 7
#define OPT_NO_GSO 8
#define OPT_QUEUE_NUM 9
#define OPT_MAX OPT_FRAG_SNI_POS
static struct option long_opt[] = {
{"help", 0, 0, 'h'},
{"version", 0, 0, 'v'},
{"sni-domains", 1, 0, OPT_SNI_DOMAINS},
{"fake-sni", 1, 0, OPT_FAKE_SNI},
{"fake-sni-seq-len", 1, 0, OPT_FAKE_SNI_SEQ_LEN},
{"faking-strategy", 1, 0, OPT_FAKING_STRATEGY},
{"faking-ttl", 1, 0, OPT_FAKING_TTL},
{"frag", 1, 0, OPT_FRAG},
{"frag-sni-reverse", 1, 0, OPT_FRAG_SNI_REVERSE},
{"frag-sni-faked", 1, 0, OPT_FRAG_SNI_FAKED},
{"frag-middle-sni", 1, 0, OPT_FRAG_MIDDLE_SNI},
{"frag-sni-pos", 1, 0, OPT_FRAG_SNI_POS},
{"fk-winsize", 1, 0, OPT_FK_WINSIZE},
{"quic-drop", 0, 0, OPT_QUIC_DROP},
{"sni-detection", 1, 0, OPT_SNI_DETECTION},
{"seg2delay", 1, 0, OPT_SEG2DELAY},
{"threads", 1, 0, OPT_THREADS},
{"silent", 0, 0, OPT_SILENT},
{"trace", 0, 0, OPT_TRACE},
{"no-gso", 0, 0, OPT_NO_GSO},
{"queue-num", 1, 0, OPT_QUEUE_NUM},
{0,0,0,0}
};
static long parse_numeric_option(const char* value) {
errno = 0;
if (*value == '\0') {
errno = EINVAL;
return 0;
}
char* end;
long result = strtol(value, &end, 10);
if (*end != '\0') {
errno = EINVAL;
return 0;
}
return result;
}
void print_version() {
printf("youtubeUnblock\n");
printf("Bypasses deep packet inspection systems that relies on SNI\n");
printf("\n");
}
void print_usage(const char *argv0) {
print_version();
printf("Usage: %s [ OPTIONS ] \n", argv0);
printf("Options:\n");
printf("\t--queue-num=<number of netfilter queue>\n");
printf("\t--sni-domains=<comma separated domain list>|all\n");
printf("\t--fake-sni={1|0}\n");
printf("\t--fake-sni-seq-len=<length>\n");
printf("\t--faking-ttl=<ttl>\n");
printf("\t--faking-strategy={randseq|ttl|tcp_check|pastseq}\n");
printf("\t--frag={tcp,ip,none}\n");
printf("\t--frag-sni-reverse={0|1}\n");
printf("\t--frag-sni-faked={0|1}\n");
printf("\t--frag-middle-sni={0|1}\n");
printf("\t--frag-sni-pos=<pos>\n");
printf("\t--fk-winsize=<winsize>\n");
printf("\t--quic-drop\n");
printf("\t--sni-detection={parse|brute}\n");
printf("\t--seg2delay=<delay>\n");
printf("\t--threads=<threads number>\n");
printf("\t--silent\n");
printf("\t--trace\n");
printf("\t--no-gso\n");
printf("\n");
}
int parse_args(int argc, char *argv[]) {
int opt;
int optIdx;
long num;
while ((opt = getopt_long(argc, argv, "hv", long_opt, &optIdx)) != -1) {
switch (opt) {
case 'h':
print_usage(argv[0]);
goto stop_exec;
case 'v':
print_version();
goto stop_exec;
case OPT_TRACE:
config.verbose = 2;
break;
case OPT_SILENT:
config.verbose = 0;
break;
case OPT_NO_GSO:
config.use_gso = 0;
break;
case OPT_QUIC_DROP:
config.quic_drop = 1;
break;
case OPT_SNI_DOMAINS:
if (!strcmp(optarg, "all")) {
config.all_domains = 1;
}
config.domains_str = optarg;
config.domains_strlen = strlen(config.domains_str);
break;
case OPT_SNI_DETECTION:
if (strcmp(optarg, "parse") == 0) {
config.sni_detection = SNI_DETECTION_PARSE;
} else if (strcmp(optarg, "brute") == 0) {
config.sni_detection = SNI_DETECTION_BRUTE;
} else {
goto invalid_opt;
}
break;
case OPT_FRAG:
if (strcmp(optarg, "tcp") == 0) {
config.fragmentation_strategy = FRAG_STRAT_TCP;
} else if (strcmp(optarg, "ip") == 0) {
config.fragmentation_strategy = FRAG_STRAT_IP;
} else if (strcmp(optarg, "none") == 0) {
config.fragmentation_strategy = FRAG_STRAT_NONE;
} else {
goto invalid_opt;
}
break;
case OPT_FRAG_SNI_FAKED:
if (strcmp(optarg, "1") == 0) {
config.frag_sni_faked = 1;
} else if (strcmp(optarg, "0") == 0) {
config.frag_sni_faked = 0;
} else {
goto invalid_opt;
}
break;
case OPT_FRAG_SNI_REVERSE:
if (strcmp(optarg, "1") == 0) {
config.frag_sni_reverse = 1;
} else if (strcmp(optarg, "0") == 0) {
config.frag_sni_reverse = 0;
} else {
goto invalid_opt;
}
break;
case OPT_FRAG_MIDDLE_SNI:
if (strcmp(optarg, "1") == 0) {
config.frag_middle_sni = 1;
} else if (strcmp(optarg, "0") == 0) {
config.frag_middle_sni = 0;
} else {
goto invalid_opt;
}
break;
case OPT_FRAG_SNI_POS:
num = parse_numeric_option(optarg);
if (errno != 0 || num < 0) {
goto invalid_opt;
}
config.frag_sni_pos = num;
break;
case OPT_FAKING_STRATEGY:
if (strcmp(optarg, "randseq") == 0) {
config.faking_strategy = FAKE_STRAT_RAND_SEQ;
} else if (strcmp(optarg, "ttl") == 0) {
config.faking_strategy = FAKE_STRAT_TTL;
} else if (strcmp(optarg, "tcp_check") == 0) {
config.faking_strategy = FAKE_STRAT_TCP_CHECK;
} else if (strcmp(optarg, "pastseq") == 0) {
config.faking_strategy = FAKE_STRAT_PAST_SEQ;
} else {
goto invalid_opt;
}
break;
case OPT_FAKING_TTL:
num = parse_numeric_option(optarg);
if (errno != 0 || num < 0 || num > 255) {
goto invalid_opt;
}
config.faking_ttl = num;
break;
case OPT_FAKE_SNI:
if (strcmp(optarg, "1") == 0) {
config.fake_sni = 1;
} else if (strcmp(optarg, "0") == 0) {
config.fake_sni = 0;
} else {
goto invalid_opt;
}
break;
case OPT_FAKE_SNI_SEQ_LEN:
num = parse_numeric_option(optarg);
if (errno != 0 || num < 0 || num > 255) {
goto invalid_opt;
}
config.fake_sni_seq_len = num;
break;
case OPT_FK_WINSIZE:
num = parse_numeric_option(optarg);
if (errno != 0 || num < 0) {
goto invalid_opt;
}
config.fk_winsize = num;
break;
case OPT_SEG2DELAY:
num = parse_numeric_option(optarg);
if (errno != 0 || num < 0) {
goto invalid_opt;
}
config.seg2_delay = num;
break;
case OPT_THREADS:
num = parse_numeric_option(optarg);
if (errno != 0 || num < 0 || num > MAX_THREADS) {
goto invalid_opt;
}
config.threads = num;
break;
case OPT_QUEUE_NUM:
num = parse_numeric_option(optarg);
if (errno != 0 || num < 0) {
goto invalid_opt;
}
config.queue_start_num = num;
break;
default:
goto error;
}
}
// out:
errno = 0;
return 0;
stop_exec:
errno = 0;
return 1;
invalid_opt:
printf("Invalid option %s\n", long_opt[optIdx].name);
error:
print_usage(argv[0]);
errno = EINVAL;
return -1;
}
void print_welcome() {
switch (config.fragmentation_strategy) {
case FRAG_STRAT_TCP:
printf("Using TCP segmentation\n");
break;
case FRAG_STRAT_IP:
printf("Using IP fragmentation\n");
break;
default:
printf("SNI fragmentation is disabled\n");
break;
}
if (config.seg2_delay) {
printf("Some outgoing googlevideo request segments will be delayed for %d ms as of seg2_delay define\n", config.seg2_delay);
}
if (config.fake_sni) {
printf("Fake SNI will be sent before each target client hello\n");
} else {
printf("Fake SNI is disabled\n");
}
if (config.frag_sni_reverse) {
printf("Fragmentation Client Hello will be reversed\n");
}
if (config.frag_sni_faked) {
printf("Fooling packets will be sent near the original Client Hello\n");
}
if (config.fake_sni_seq_len > 1) {
printf("Faking sequence of length %d will be built as fake sni\n", config.fake_sni_seq_len);
}
switch (config.faking_strategy) {
case FAKE_STRAT_TTL:
printf("TTL faking strategy will be used with TTL %d\n", config.faking_ttl);
break;
case FAKE_STRAT_RAND_SEQ:
printf("Random seq faking strategy will be used\n");
break;
case FAKE_STRAT_TCP_CHECK:
printf("TCP checksum faking strategy will be used\n");
break;
case FAKE_STRAT_PAST_SEQ:
printf("Past seq faking strategy will be used\n");
break;
}
if (config.fk_winsize) {
printf("Response TCP window will be set to %d with the appropriate scale\n", config.fk_winsize);
}
if (config.use_gso) {
printf("GSO is enabled\n");
}
if (config.quic_drop) {
printf("All QUIC packets will be dropped\n");
}
if (config.sni_detection == SNI_DETECTION_BRUTE) {
printf("Server Name Extension will be parsed in the bruteforce mode\n");
}
if (config.all_domains) {
printf("All Client Hello will be targetted by youtubeUnblock!\n");
}
}