Require a target node for NAT port forward configuration

This commit is contained in:
evgeny committed 2026-10-21 21:54:41 +02:00
1 parent 3d0c4ff0a5
commit 2c4f107e63
3 files changed
+64 -25

No files matched your search

+62 -24
View File
@@ -551,15 +551,26 @@ static int parse_nat(const char *key, const char *value, struct global_config *g
return 0;
}
if (strcmp(key, "nat_via") == 0) {
global->nat_via_node_id = strtoull(value, NULL, 16);
char* end;
errno = 0;
uint64_t node_id = strtoull(value, &end, 16);
if (!*value || *value == '-' || *value == '+' || *end || errno == ERANGE) {
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Invalid NAT provider ID: %s", filename, line_num, value);
return -1;
}
global->nat_via_node_id = node_id;
return 0;
}
if (strcmp(key, "port_start") == 0) {
global->nat_port_start = (uint16_t)atoi(value);
return 0;
}
if (strcmp(key, "port_end") == 0) {
global->nat_port_end = (uint16_t)atoi(value);
if (strcmp(key, "port_start") == 0 || strcmp(key, "port_end") == 0) {
char* end;
errno = 0;
unsigned long port = strtoul(value, &end, 10);
if (!isdigit((unsigned char)*value) || *end || errno == ERANGE || port == 0 || port > 65535) {
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Invalid NAT %s: %s (expected 1..65535)", filename, line_num, key, value);
return -1;
}
if (strcmp(key, "port_start") == 0) global->nat_port_start = (uint16_t)port;
else global->nat_port_end = (uint16_t)port;
return 0;
}
if (strcmp(key, "forward") == 0) {
@@ -567,21 +578,44 @@ static int parse_nat(const char *key, const char *value, struct global_config *g
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Too many NAT forward rules (max %d)", MAX_NAT_FORWARDS);
return -1;
}
// Format: proto:internal_ip:internal_port:external_port
// Example: tcp:192.168.1.100:8080:8080
// Format: proto:node_id_hex:internal_ip:internal_port:external_port.
char buf[128];
strncpy(buf, value, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
config_ini_trim(buf);
char* proto_str = strtok(buf, ":");
char* ip_str = strtok(NULL, ":");
char* int_port = strtok(NULL, ":");
char* ext_port = strtok(NULL, ":");
if (!proto_str || !ip_str || !int_port || !ext_port) {
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Invalid NAT forward format: %s (expected proto:ip:internal_port:external_port)", value);
if (strlen(value) >= sizeof(buf)) {
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: NAT forward value too long", filename, line_num);
return -1;
}
strcpy(buf, value);
char* fields[5];
char* cursor = buf;
for (int i = 0; i < 5; i++) {
fields[i] = cursor;
char* colon = strchr(cursor, ':');
if ((i < 4 && !colon) || (i == 4 && colon) || !*cursor || colon == cursor) {
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Invalid NAT forward: %s (proto:node_id:ip:internal_port:external_port)",
filename, line_num, value);
return -1;
}
if (colon) { *colon = '\0'; cursor = colon + 1; }
}
char* proto_str = fields[0];
char* ip_str = fields[2];
char* end;
errno = 0;
uint64_t node_id = strtoull(fields[1], &end, 16);
if (!node_id || *fields[1] == '-' || *fields[1] == '+' || *end || errno == ERANGE) {
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Invalid NAT forward node ID: %s", filename, line_num, fields[1]);
return -1;
}
uint16_t ports[2];
for (int i = 0; i < 2; i++) {
errno = 0;
unsigned long port = strtoul(fields[i + 3], &end, 10);
if (!isdigit((unsigned char)*fields[i + 3]) || *end || errno == ERANGE || port == 0 || port > 65535) {
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Invalid NAT forward port: %s", filename, line_num, fields[i + 3]);
return -1;
}
ports[i] = (uint16_t)port;
}
uint8_t proto;
if (strcasecmp(proto_str, "tcp") == 0) proto = IPPROTO_TCP;
@@ -598,13 +632,14 @@ static int parse_nat(const char *key, const char *value, struct global_config *g
}
int idx = global->nat_forward_count;
global->nat_forwards[idx].node_id = node_id;
global->nat_forwards[idx].proto = proto;
global->nat_forwards[idx].internal_ip_host = ntohl(addr.s_addr);
global->nat_forwards[idx].internal_port_net = htons((uint16_t)atoi(int_port));
global->nat_forwards[idx].external_port = (uint16_t)atoi(ext_port);
global->nat_forwards[idx].internal_port_net = htons(ports[0]);
global->nat_forwards[idx].external_port = ports[1];
global->nat_forward_count++;
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "NAT forward: %s %s:%s -> :%s",
proto_str, ip_str, int_port, ext_port);
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "NAT forward: :%u -> node=%016llx %s %s:%u",
ports[1], (unsigned long long)node_id, proto_str, ip_str, ports[0]);
return 0;
}
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Unknown NAT option '%s'. Valid: tun_ifname, tun_ip, nat_via, port_start, port_end, forward", filename, line_num, key);
@@ -1103,7 +1138,10 @@ struct utun_config* parse_config_from_buf(const char *buf, size_t len, const cha
break;
case SECTION_CONTROL: parse_control(key, value, &cfg->global, filename, line_num); break;
case SECTION_ALLOWED_KEYS: if (strcmp(key, "allow_all") == 0) cfg->global.allowed_keys_allow_all = strcasecmp(value, "yes") == 0 || strcasecmp(value, "1") == 0 || strcasecmp(value, "true") == 0; else if (strcmp(key, "key") == 0) { struct CFG_ALLOWED_KEY *nk = u_calloc(1, sizeof(struct CFG_ALLOWED_KEY)); if (nk && strlen(value) == SC_PUBKEY_SIZE * 2 && config_ini_hex(value, nk->key_bin, SC_PUBKEY_SIZE) == 0) { nk->next = cfg->global.allowed_keys; cfg->global.allowed_keys = nk; cfg->global.allowed_keys_count++; } else u_free(nk); } else DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "%s:%d: Unknown allowed_keys option '%s'", filename, line_num, key); break;
case SECTION_NAT: cfg->global.nat_enabled = 1; parse_nat(key, value, &cfg->global, filename, line_num); break;
case SECTION_NAT:
cfg->global.nat_enabled = 1;
if (parse_nat(key, value, &cfg->global, filename, line_num) < 0) goto error;
break;
case SECTION_TCP_PROXY_CLIENT: cfg->global.tcp_proxy_client_enabled = 1; parse_tcp_proxy_client(key, value, &cfg->global, filename, line_num); break;
case SECTION_TCP_PROXY_SERVER:
cfg->global.tcp_proxy_server_enabled = 1;
+1
View File
@@ -193,6 +193,7 @@ struct global_config {
uint16_t nat_port_end;
#define MAX_NAT_FORWARDS 64
struct {
uint64_t node_id; // Узел назначения статического проброса; ненулевой ID.
uint8_t proto;
uint32_t internal_ip_host;
uint16_t internal_port_net;
+1 -1
View File
@@ -65,7 +65,7 @@ int eim_nat_ingress(struct eim_nat_ctx* ctx, uint8_t* ip_data, size_t ip_len,
int eim_nat_add_forward(struct eim_nat_ctx* ctx, uint8_t proto,
uint32_t internal_ip_host, uint16_t internal_port_net,
uint16_t external_port);
uint16_t external_port, uint64_t node_id);
#ifdef __cplusplus