Validate provider replies before client TUN delivery
This commit is contained in:
1 parent
5e2e6c15cf
commit
cecc5d7d1f
3 files changed
+25
-5
No files matched your search
+13
-5
@@ -117,9 +117,9 @@ static struct eim_nat_entry* eim_nat_insert(struct eim_nat_ctx* ctx, uint16_t ex
|
||||
// ==================== Public API ====================
|
||||
|
||||
// Проверить полный IPv4 и границы транспорта до изменения пакета/таблицы. memcpy допускает любой alignment.
|
||||
static int eim_nat_parse_packet(struct eim_nat_ctx* ctx, const uint8_t* ip, size_t len, uint16_t* header_len) {
|
||||
if (!ctx || !ctx->initialized || !ctx->table || !ip || len < IP_HDR_MIN_SIZE) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT invalid packet/context: ctx=%p data=%p bytes=%zu", (void*)ctx, (const void*)ip, len);
|
||||
int eim_nat_validate_packet(const uint8_t* ip, size_t len, uint16_t* header_len) {
|
||||
if (!header_len || !ip || len < IP_HDR_MIN_SIZE) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT invalid packet: data=%p bytes=%zu header=%p", (const void*)ip, len, (void*)header_len);
|
||||
return EIM_NAT_ERROR;
|
||||
}
|
||||
*header_len = (ip[0] & 15) * 4;
|
||||
@@ -158,8 +158,12 @@ static int eim_nat_parse_packet(struct eim_nat_ctx* ctx, const uint8_t* ip, size
|
||||
|
||||
int eim_nat_egress(struct eim_nat_ctx* ctx, uint8_t* ip_data, size_t ip_len,
|
||||
uint64_t src_node_id, struct ETCP_CONN* src_conn) {
|
||||
if (!ctx || !ctx->initialized || !ctx->table || !ctx->buckets) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "NAT egress requires initialized context");
|
||||
return EIM_NAT_ERROR;
|
||||
}
|
||||
uint16_t ip_hdr_len;
|
||||
int parsed = eim_nat_parse_packet(ctx, ip_data, ip_len, &ip_hdr_len);
|
||||
int parsed = eim_nat_validate_packet(ip_data, ip_len, &ip_hdr_len);
|
||||
if (parsed != EIM_NAT_OK) return parsed;
|
||||
|
||||
uint8_t proto = ip_data[IP_PROTO_OFFSET];
|
||||
@@ -224,8 +228,12 @@ int eim_nat_egress(struct eim_nat_ctx* ctx, uint8_t* ip_data, size_t ip_len,
|
||||
int eim_nat_ingress(struct eim_nat_ctx* ctx, uint8_t* ip_data, size_t ip_len,
|
||||
struct eim_nat_entry** out_entry) {
|
||||
if (out_entry) *out_entry = NULL;
|
||||
if (!ctx || !ctx->initialized || !ctx->table || !ctx->buckets) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "NAT ingress requires initialized context");
|
||||
return EIM_NAT_ERROR;
|
||||
}
|
||||
uint16_t ip_hdr_len;
|
||||
int parsed = eim_nat_parse_packet(ctx, ip_data, ip_len, &ip_hdr_len);
|
||||
int parsed = eim_nat_validate_packet(ip_data, ip_len, &ip_hdr_len);
|
||||
if (parsed != EIM_NAT_OK) return parsed;
|
||||
|
||||
uint8_t proto = ip_data[IP_PROTO_OFFSET];
|
||||
|
||||
@@ -66,6 +66,11 @@ struct eim_nat_ctx {
|
||||
|
||||
struct global_config;
|
||||
|
||||
/* Проверить IPv4 и транспортные границы без изменения данных. header_len обязателен и получает IHL в байтах.
|
||||
* EIM_NAT_OK — поддерживаемый полный пакет; SKIP — фрагмент/неподдерживаемый протокол; ERROR — неверный формат.
|
||||
* Checksums не проверяются. Не требует созданного NAT ctx. */
|
||||
int eim_nat_validate_packet(const uint8_t* ip, size_t len, uint16_t* header_len);
|
||||
|
||||
/* Создать ctx по g: IPv4 шлюза, 1 <= port_start < port_end <= 65535, статические пробросы.
|
||||
* ctx не должен владеть предыдущей таблицей: перед повторным init вызвать destroy_ctx.
|
||||
* 0 — успех (при !nat_enabled таблица не создаётся); -1 — ошибка, созданная таблица освобождена. */
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "nat_transport.h"
|
||||
#include "etcp.h"
|
||||
#include "eim_nat.h"
|
||||
#include "utun_instance.h"
|
||||
#include "config_parser.h"
|
||||
@@ -219,6 +220,12 @@ static void nat_receive(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
if (!tr->nat_via_node_id) {
|
||||
int result = eim_nat_egress(&inst->nat, entry->dgram + ROUTER_SVC_PAYLOAD_OFF, len, source, conn);
|
||||
if (result != EIM_NAT_OK) { nat_drop(inst, entry, source, "egress invalid or unsupported packet"); return; }
|
||||
} else {
|
||||
uint16_t header_len;
|
||||
if (eim_nat_validate_packet(entry->dgram + ROUTER_SVC_PAYLOAD_OFF, len, &header_len) != EIM_NAT_OK) {
|
||||
nat_drop(inst, entry, source, "invalid provider IPv4 packet");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (tr->tun_pending) { nat_drop(inst, entry, source, "concurrent TUN delivery"); return; } // Возможен только loopback.
|
||||
tr->tun_pending = entry;
|
||||
|
||||
Reference in new issue
Block a user