Route static NAT forwards to explicit owners on all ports
This commit is contained in:
1 parent
2c4f107e63
commit
ca471d777e
3 files changed
+33
-25
No files matched your search
+29
-19
@@ -70,10 +70,10 @@ static void csum_update_icmp(uint8_t* icmp, uint16_t old_word, uint16_t new_word
|
||||
memcpy(icmp + ICMP_CHECKSUM_OFFSET, &new_csum, 2);
|
||||
}
|
||||
|
||||
// Поиск в замкнутом диапазоне; индекс должен вмещать 65536 после последнего порта.
|
||||
// Статические порты могут лежать вне динамического диапазона; индекс вмещает 65536.
|
||||
static struct eim_nat_entry* eim_nat_find_egress(struct eim_nat_ctx* ctx,
|
||||
uint8_t proto, uint32_t ip_host, uint16_t port_net, uint64_t src_node_id) {
|
||||
for (uint32_t i = ctx->port_start; i <= ctx->port_end; i++) {
|
||||
for (uint32_t i = 1; i < ctx->table_size; i++) {
|
||||
struct eim_nat_entry* e = &ctx->table[i];
|
||||
if (e->state != EIM_NAT_ENTRY_FREE && e->proto == proto && e->src_node_id == src_node_id &&
|
||||
e->internal_ip == ip_host && e->internal_port == port_net) return e;
|
||||
@@ -208,8 +208,6 @@ int eim_nat_ingress(struct eim_nat_ctx* ctx, uint8_t* ip_data, size_t ip_len,
|
||||
if (!is_tcp && !is_udp && !is_icmp_echo) return 0;
|
||||
|
||||
uint16_t ext_port_host = ntohs(dst_port_net);
|
||||
if (ext_port_host < ctx->port_start || ext_port_host > ctx->port_end) return 0;
|
||||
|
||||
struct eim_nat_entry* entry = &ctx->table[ext_port_host];
|
||||
if (entry->state == EIM_NAT_ENTRY_FREE) return 0;
|
||||
if (entry->proto != proto) return 0;
|
||||
@@ -264,24 +262,25 @@ int eim_nat_init_ctx(struct eim_nat_ctx* ctx, const struct global_config* g) {
|
||||
return -1;
|
||||
}
|
||||
ctx->next_port = ctx->port_start;
|
||||
if (g->nat_forward_count < 0 || g->nat_forward_count > MAX_NAT_FORWARDS) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Invalid NAT forward count: %d", g->nat_forward_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->table_size = EIM_NAT_TABLE_SIZE;
|
||||
ctx->table = u_calloc(ctx->table_size, sizeof(struct eim_nat_entry));
|
||||
if (!ctx->table) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Failed to allocate NAT table"); return -1; }
|
||||
ctx->initialized = 1;
|
||||
|
||||
for (int i = 0; i < g->nat_forward_count; i++) {
|
||||
uint16_t ext = g->nat_forwards[i].external_port;
|
||||
if (ext >= ctx->table_size) continue;
|
||||
struct eim_nat_entry* e = &ctx->table[ext];
|
||||
e->internal_ip = g->nat_forwards[i].internal_ip_host;
|
||||
e->internal_port = g->nat_forwards[i].internal_port_net;
|
||||
e->proto = g->nat_forwards[i].proto;
|
||||
e->state = EIM_NAT_ENTRY_STATIC;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NAT, "Port forward: %s:%u <- :%u (proto=%u)",
|
||||
ip_host_to_str(e->internal_ip).str, ntohs(e->internal_port), ext, e->proto);
|
||||
if (eim_nat_add_forward(ctx, g->nat_forwards[i].proto, g->nat_forwards[i].internal_ip_host,
|
||||
g->nat_forwards[i].internal_port_net, g->nat_forwards[i].external_port, g->nat_forwards[i].node_id) != 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Invalid NAT forward at index %d; initialization aborted", i);
|
||||
eim_nat_destroy_ctx(ctx);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->initialized = 1;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NAT, "NAT engine initialized: gw=%s ports=%u-%u",
|
||||
ip_host_to_str(ctx->gateway_ip).str, ctx->port_start, ctx->port_end);
|
||||
return 0;
|
||||
@@ -296,15 +295,26 @@ void eim_nat_destroy_ctx(struct eim_nat_ctx* ctx) {
|
||||
|
||||
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) {
|
||||
if (!ctx || !ctx->initialized || external_port >= ctx->table_size) return -1;
|
||||
if (ctx->table[external_port].state != EIM_NAT_ENTRY_FREE) return -1;
|
||||
uint16_t external_port, uint64_t node_id) {
|
||||
if (!ctx || !ctx->initialized || !node_id || !external_port || !internal_port_net ||
|
||||
(proto != IPPROTO_TCP_UINT8 && proto != IPPROTO_UDP_UINT8) || external_port >= ctx->table_size) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Invalid NAT forward: ctx=%p node=%016llx proto=%u internal_port=%u external_port=%u",
|
||||
(void*)ctx, (unsigned long long)node_id, proto, ntohs(internal_port_net), external_port);
|
||||
return -1;
|
||||
}
|
||||
if (ctx->table[external_port].state != EIM_NAT_ENTRY_FREE ||
|
||||
eim_nat_find_egress(ctx, proto, internal_ip_host, internal_port_net, node_id)) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "NAT forward conflicts with existing mapping: node=%016llx %s:%u <- :%u proto=%u",
|
||||
(unsigned long long)node_id, ip_host_to_str(internal_ip_host).str, ntohs(internal_port_net), external_port, proto);
|
||||
return -1;
|
||||
}
|
||||
struct eim_nat_entry* e = &ctx->table[external_port];
|
||||
e->internal_ip = internal_ip_host;
|
||||
e->internal_port = internal_port_net;
|
||||
e->proto = proto;
|
||||
e->state = EIM_NAT_ENTRY_STATIC;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NAT, "Port forward: %s:%u <- :%u (proto=%u)",
|
||||
ip_host_to_str(internal_ip_host).str, ntohs(internal_port_net), external_port, proto);
|
||||
e->src_node_id = node_id;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NAT, "Port forward: node=%016llx %s:%u <- :%u (proto=%u)",
|
||||
(unsigned long long)node_id, ip_host_to_str(internal_ip_host).str, ntohs(internal_port_net), external_port, proto);
|
||||
return 0;
|
||||
}
|
||||
@@ -740,7 +740,7 @@ static void test_port_forward(void) {
|
||||
|
||||
int r = eim_nat_add_forward(&ctx, IPPROTO_TCP_UINT8,
|
||||
0x0A0000FE, htobe16(8080), // internal 10.0.0.254:8080
|
||||
10050);
|
||||
10050, 1);
|
||||
ASSERT_EQ(r, 0, "add_forward ok");
|
||||
ASSERT(ctx.table[10050].state == EIM_NAT_ENTRY_STATIC, "entry static");
|
||||
ASSERT_EQ(ctx.table[10050].internal_ip, 0x0A0000FE, "internal_ip");
|
||||
@@ -756,8 +756,8 @@ static void test_port_forward(void) {
|
||||
struct eim_nat_ctx ctx;
|
||||
eim_nat_init_ctx(&ctx, &g);
|
||||
|
||||
eim_nat_add_forward(&ctx, IPPROTO_TCP_UINT8, 0x0A0000FE, htobe16(8080), 10050);
|
||||
int r = eim_nat_add_forward(&ctx, IPPROTO_UDP_UINT8, 0x0A0000FF, htobe16(9090), 10050);
|
||||
eim_nat_add_forward(&ctx, IPPROTO_TCP_UINT8, 0x0A0000FE, htobe16(8080), 10050, 1);
|
||||
int r = eim_nat_add_forward(&ctx, IPPROTO_UDP_UINT8, 0x0A0000FF, htobe16(9090), 10050, 1);
|
||||
ASSERT_EQ(r, -1, "duplicate rejects");
|
||||
eim_nat_destroy_ctx(&ctx);
|
||||
}
|
||||
@@ -770,7 +770,7 @@ static void test_port_forward(void) {
|
||||
eim_nat_init_ctx(&ctx, &g);
|
||||
|
||||
// Static forward: external port 10050 → internal 10.0.0.254:8080 TCP
|
||||
eim_nat_add_forward(&ctx, IPPROTO_TCP_UINT8, 0x0A0000FE, htobe16(8080), 10050);
|
||||
eim_nat_add_forward(&ctx, IPPROTO_TCP_UINT8, 0x0A0000FE, htobe16(8080), 10050, 1);
|
||||
|
||||
// Ingress TCP packet to gateway:10050
|
||||
uint8_t* resp = make_tcp_pkt(TEST_IP_DST_HOST, 443, TEST_GW_HOST, 10050);
|
||||
|
||||
@@ -138,7 +138,6 @@ static int create_temp_configs(void) {
|
||||
"allow_all=1\n"
|
||||
"\n"
|
||||
"[nat]\n"
|
||||
"enabled=1\n"
|
||||
"tun_ifname=tun_nat\n"
|
||||
"tun_ip=100.64.0.1/24\n"
|
||||
"port_start=20000\n"
|
||||
@@ -166,7 +165,6 @@ static int create_temp_configs(void) {
|
||||
"link=cl:127.0.0.1:0\n"
|
||||
"\n"
|
||||
"[nat]\n"
|
||||
"enabled=1\n"
|
||||
"tun_ifname=tun_nat_client\n"
|
||||
"tun_ip=100.64.1.1/24\n"
|
||||
"nat_via=0x%016llx\n",
|
||||
|
||||
Reference in new issue
Block a user