reality: TLS-камуфляж для STCP (ClientHello/ServerHello + релей на реальный сайт)
This commit is contained in:
1 parent
0f308fdbd7
commit
edb3bb36e1
23 files changed
+1614
-28
No files matched your search
+80
-2
@@ -52,7 +52,8 @@ typedef enum {
|
||||
SECTION_NETWORK,
|
||||
SECTION_GUI,
|
||||
SECTION_NTP,
|
||||
SECTION_LOG_UDP
|
||||
SECTION_LOG_UDP,
|
||||
SECTION_REALITY
|
||||
} section_type_t;
|
||||
|
||||
static char* trim(char *str) {
|
||||
@@ -698,7 +699,11 @@ static int parse_server(const char *key, const char *value, struct CFG_SERVER *s
|
||||
else srv->transport = 0; // default udp
|
||||
return 0;
|
||||
}
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Unknown server option '%s'. Valid: addr, so_mark, fib, netif, type, mtu, only_local, transport", filename, line_num, key);
|
||||
if (strcmp(key, "reality") == 0) {
|
||||
srv->reality_enabled = atoi(value) ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Unknown server option '%s'. Valid: addr, so_mark, fib, netif, type, mtu, only_local, transport, reality", filename, line_num, key);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -808,6 +813,72 @@ static int parse_network(const char *key, const char *value, struct CFG_NETWORK
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int parse_reality(const char *key, const char *value, struct reality_config *rc, const char *filename, int line_num) {
|
||||
if (strcmp(key, "enabled") == 0) { rc->enabled = atoi(value) ? 1 : 0; return 0; }
|
||||
if (strcmp(key, "server_name") == 0) { return assign_string(rc->server_name, sizeof(rc->server_name), value); }
|
||||
if (strcmp(key, "dest") == 0) { return assign_string(rc->dest, sizeof(rc->dest), value); }
|
||||
if (strcmp(key, "short_id") == 0) {
|
||||
if (hex_to_binary(value, rc->short_id, REALITY_SHORT_ID_SIZE) < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: reality short_id must be %d hex chars", filename, line_num, REALITY_SHORT_ID_SIZE * 2);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(key, "short_ids") == 0) {
|
||||
rc->short_id_count = 0;
|
||||
char buf[MAX_LINE_LEN];
|
||||
assign_string(buf, sizeof(buf), value);
|
||||
char *tok = strtok(buf, ",");
|
||||
while (tok) {
|
||||
char *t = trim(tok);
|
||||
if (rc->short_id_count >= REALITY_MAX_SHORT_IDS) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: too many reality short_ids (max %d)", filename, line_num, REALITY_MAX_SHORT_IDS);
|
||||
return -1;
|
||||
}
|
||||
if (hex_to_binary(t, rc->short_ids[rc->short_id_count], REALITY_SHORT_ID_SIZE) < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: bad reality short_id '%s'", filename, line_num, t);
|
||||
return -1;
|
||||
}
|
||||
rc->short_id_count++;
|
||||
tok = strtok(NULL, ",");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(key, "public_key") == 0) {
|
||||
if (hex_to_binary(value, rc->public_key, REALITY_AUTH_KEY_SIZE) < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: reality public_key must be %d hex chars", filename, line_num, REALITY_AUTH_KEY_SIZE * 2);
|
||||
return -1;
|
||||
}
|
||||
rc->has_public_key = 1;
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(key, "private_key") == 0) {
|
||||
if (hex_to_binary(value, rc->private_key, REALITY_AUTH_KEY_SIZE) < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: reality private_key must be %d hex chars", filename, line_num, REALITY_AUTH_KEY_SIZE * 2);
|
||||
return -1;
|
||||
}
|
||||
rc->has_private_key = 1;
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(key, "version") == 0) {
|
||||
int x = 0, y = 0, z = 0;
|
||||
if (sscanf(value, "%d.%d.%d", &x, &y, &z) != 3 || x < 0 || x > 255 || y < 0 || y > 255 || z < 0 || z > 255) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: bad reality version '%s' (expected x.y.z)", filename, line_num, value);
|
||||
return -1;
|
||||
}
|
||||
rc->version[0] = (uint8_t)x; rc->version[1] = (uint8_t)y; rc->version[2] = (uint8_t)z;
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(key, "time_window") == 0) { rc->time_window_sec = atoi(value); return 0; }
|
||||
if (strcmp(key, "fingerprint") == 0) {
|
||||
if (strcmp(value, "chrome") == 0) { rc->fingerprint = REALITY_FP_CHROME; return 0; }
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: unknown reality fingerprint '%s' (valid: chrome)", filename, line_num, value);
|
||||
return -1;
|
||||
}
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Unknown reality option '%s'. Valid: enabled, server_name, dest, short_id, short_ids, public_key, private_key, version, time_window, fingerprint", filename, line_num, key);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static section_type_t parse_section_header(const char *line, char *name, size_t name_len) {
|
||||
if (line[0] != '[') return SECTION_UNKNOWN;
|
||||
|
||||
@@ -835,6 +906,7 @@ static section_type_t parse_section_header(const char *line, char *name, size_t
|
||||
if (strcasecmp(section, "ntp") == 0) return SECTION_NTP;
|
||||
if (strcasecmp(section, "gui") == 0) return SECTION_GUI;
|
||||
if (strcasecmp(section, "log_udp") == 0) return SECTION_LOG_UDP;
|
||||
if (strcasecmp(section, "reality") == 0) return SECTION_REALITY;
|
||||
|
||||
char *colon = strchr(section, ':');
|
||||
if (!colon) return SECTION_UNKNOWN;
|
||||
@@ -887,6 +959,7 @@ static struct utun_config* parse_config_internal(FILE *fp, const char *filename)
|
||||
cfg->global.chatserver_allowed_groups[0] = '\0';
|
||||
cfg->global.chatserver_storage_total_size = 0;
|
||||
cfg->global.chatserver_storage_unit_size = 0;
|
||||
reality_config_set_defaults(&cfg->global.reality);
|
||||
|
||||
section_type_t cur_section = SECTION_UNKNOWN;
|
||||
struct CFG_SERVER *cur_server = NULL;
|
||||
@@ -1098,6 +1171,9 @@ static struct utun_config* parse_config_internal(FILE *fp, const char *filename)
|
||||
break;
|
||||
case SECTION_GUI:
|
||||
break;
|
||||
case SECTION_REALITY:
|
||||
parse_reality(key, value, &cfg->global.reality, filename, line_num);
|
||||
break;
|
||||
default:
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "%s:%d: Key outside section: %s", filename, line_num, key);
|
||||
break;
|
||||
@@ -1187,6 +1263,7 @@ struct utun_config* parse_config_from_buf(const char *buf, size_t len, const cha
|
||||
cfg->global.chatserver_allowed_groups[0] = '\0';
|
||||
cfg->global.chatserver_storage_total_size = 0;
|
||||
cfg->global.chatserver_storage_unit_size = 0;
|
||||
reality_config_set_defaults(&cfg->global.reality);
|
||||
|
||||
section_type_t cur_section = SECTION_UNKNOWN;
|
||||
struct CFG_SERVER *cur_server = NULL;
|
||||
@@ -1247,6 +1324,7 @@ struct utun_config* parse_config_from_buf(const char *buf, size_t len, const cha
|
||||
case SECTION_NTP: if (strcmp(key, "enabled") == 0) cfg->global.ntp_enabled = strcasecmp(value, "yes") == 0 || strcasecmp(value, "1") == 0 || strcasecmp(value, "true") == 0; else if (strcmp(key, "server") == 0) { struct CFG_NTP_SERVER *ns = u_calloc(1, sizeof(struct CFG_NTP_SERVER)); if (ns) { strncpy(ns->name, value, sizeof(ns->name) - 1); ns->name[sizeof(ns->name) - 1] = '\0'; ns->next = cfg->global.ntp_servers; cfg->global.ntp_servers = ns; cfg->global.ntp_server_count++; } } else if (strcmp(key, "interval") == 0) { cfg->global.ntp_resync_interval = atoi(value); if (cfg->global.ntp_resync_interval < 60) cfg->global.ntp_resync_interval = 60; } else DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Unknown ntp option '%s'", filename, line_num, key); break;
|
||||
case SECTION_CHATSERVER: cfg->global.chatserver_enabled = 1; cfg->global.db_sync_enabled = 1; if (strcmp(key, "db_path") == 0) assign_string(cfg->global.db_path, sizeof(cfg->global.db_path), value); else if (parse_chatserver(key, value, &cfg->global, filename, line_num) < 0 && chat_setting_set(key, value) < 0) { DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Unknown chatserver option '%s'. Valid: db_path, join_password, allowed_groups, storage_total_size, storage_unit_size, storage_autoload, opus_codec_preset, compressor_enabled, compressor_max_gain_db, compressor_rise_rate, media_download_max_peers", filename, line_num, key); } break;
|
||||
case SECTION_GUI: break;
|
||||
case SECTION_REALITY: parse_reality(key, value, &cfg->global.reality, filename, line_num); break;
|
||||
case SECTION_LOG_UDP:
|
||||
if (strcmp(key, "ip") == 0) strncpy(cfg->global.log_udp_ip, value, sizeof(cfg->global.log_udp_ip) - 1);
|
||||
else if (strcmp(key, "port") == 0) cfg->global.log_udp_port = atoi(value);
|
||||
|
||||
Reference in new issue
Block a user