netfilter_nft: rule_t: have src/dst/nat addresses and ports

instead of guessing if it is remote host / external or internal address...
This commit is contained in:
Thomas Bernard 2023-11-22 01:56:24 +01:00
parent 25206a7a3f
commit 90fb7801eb
No known key found for this signature in database
GPG Key ID: DB511043A31ACAAF
4 changed files with 76 additions and 80 deletions

View File

@ -292,7 +292,7 @@ delete_filter_rule(const char * ifname, unsigned short port, int proto)
refresh_nft_cache_filter();
LIST_FOREACH(p, &head_filter, entry) {
if (p->eport == port && p->proto == proto && p->type == RULE_FILTER) {
if (p->dport == port && p->proto == proto && p->type == RULE_FILTER) {
r = rule_del_handle(p);
nft_send_rule(r, NFT_MSG_DELRULE, RULE_CHAIN_FILTER);
break;
@ -318,10 +318,10 @@ delete_redirect_and_filter_rules(unsigned short eport, int proto)
// Delete Redirect Rule
LIST_FOREACH(p, &head_redirect, entry) {
if (p->eport == eport && p->proto == proto &&
if (p->dport == eport && p->proto == proto &&
(p->type == RULE_NAT && p->nat_type == NFT_NAT_DNAT)) {
iaddr = p->iaddr;
iport = p->iport;
iaddr = p->nat_addr;
iport = p->nat_port;
r = rule_del_handle(p);
/* Todo: send bulk request */
@ -334,8 +334,8 @@ delete_redirect_and_filter_rules(unsigned short eport, int proto)
refresh_nft_cache_filter();
// Delete Forward Rule
LIST_FOREACH(p, &head_filter, entry) {
if (p->eport == iport &&
p->iaddr == iaddr && p->type == RULE_FILTER) {
if (p->nat_port == iport &&
p->nat_addr == iaddr && p->type == RULE_FILTER) {
r = rule_del_handle(p);
/* Todo: send bulk request */
nft_send_rule(r, NFT_MSG_DELRULE, RULE_CHAIN_FILTER);
@ -350,10 +350,10 @@ delete_redirect_and_filter_rules(unsigned short eport, int proto)
refresh_nft_cache_peer();
// Delete Peer Rule
LIST_FOREACH(p, &head_peer, entry) {
if (p->eport == eport && p->proto == proto &&
if (p->nat_port == eport && p->proto == proto &&
(p->type == RULE_NAT && p->nat_type == NFT_NAT_SNAT)) {
iaddr = p->iaddr;
iport = p->iport;
iaddr = p->daddr;
iport = p->dport;
r = rule_del_handle(p);
/* Todo: send bulk request */
@ -366,8 +366,8 @@ delete_redirect_and_filter_rules(unsigned short eport, int proto)
refresh_nft_cache_filter();
// Delete Forward Rule
LIST_FOREACH(p, &head_filter, entry) {
if (p->eport == iport &&
p->iaddr == iaddr && p->type == RULE_FILTER) {
if (p->dport == iport &&
p->daddr == iaddr && p->type == RULE_FILTER) {
r = rule_del_handle(p);
/* Todo: send bulk request */
nft_send_rule(r, NFT_MSG_DELRULE, RULE_CHAIN_FILTER);
@ -405,18 +405,18 @@ get_peer_rule_by_index(int index,
}
if (eport != NULL) {
*eport = r->eport;
*eport = r->nat_port;
}
if (iaddr != NULL) {
if (inet_ntop(AF_INET, &r->iaddr, iaddr, iaddrlen) == NULL) {
if (inet_ntop(AF_INET, &r->daddr, iaddr, iaddrlen) == NULL) {
syslog(LOG_ERR, "%s: inet_ntop: %m",
"get_peer_rule_by_index");
}
}
if (iport != NULL) {
*iport = r->iport;
*iport = r->dport;
}
if (proto != NULL) {
@ -424,8 +424,8 @@ get_peer_rule_by_index(int index,
}
if (rhost != NULL) {
if (r->rhost) {
if (inet_ntop(AF_INET, &r->rhost, rhost, rhostlen) == NULL) {
if (r->saddr) {
if (inet_ntop(AF_INET, &r->saddr, rhost, rhostlen) == NULL) {
syslog(LOG_ERR, "%s: inet_ntop: %m",
"get_peer_rule_by_index");
}
@ -435,7 +435,7 @@ get_peer_rule_by_index(int index,
}
if (rport != NULL) {
*rport = r->rport;
*rport = r->sport;
}
if (desc != NULL) {
@ -450,7 +450,7 @@ get_peer_rule_by_index(int index,
}
if (timestamp) {
*timestamp = get_timestamp(r->eport, r->proto);
*timestamp = get_timestamp(r->dport, r->proto);
}
/*
* TODO: Implement counter in case of add {nat,filter}
@ -524,18 +524,18 @@ get_redirect_rule_by_index(int index,
}
if (eport != NULL) {
*eport = r->eport;
*eport = r->dport;
}
if (iaddr != NULL) {
if (inet_ntop(AF_INET, &r->iaddr, iaddr, iaddrlen) == NULL) {
if (inet_ntop(AF_INET, &r->nat_addr, iaddr, iaddrlen) == NULL) {
syslog(LOG_ERR, "%s: inet_ntop: %m",
"get_redirect_rule_by_index");
}
}
if (iport != NULL) {
*iport = r->iport;
*iport = r->nat_port;
}
if (proto != NULL) {
@ -543,8 +543,8 @@ get_redirect_rule_by_index(int index,
}
if (rhost != NULL) {
if (r->rhost) {
if (inet_ntop(AF_INET, &r->rhost, rhost, rhostlen) == NULL) {
if (r->saddr) {
if (inet_ntop(AF_INET, &r->saddr, rhost, rhostlen) == NULL) {
syslog(LOG_ERR, "%s: inet_ntop: %m",
"get_redirect_rule_by_index");
}
@ -604,10 +604,10 @@ get_nat_redirect_rule(const char * nat_chain_name, const char * ifname,
LIST_FOREACH(p, &head_redirect, entry) {
if (p->proto == proto &&
p->eport == eport) {
p->dport == eport) {
if (p->iaddr && iaddr) {
addr.s_addr = p->iaddr;
if (p->nat_addr && iaddr) {
addr.s_addr = p->nat_addr;
if (inet_ntop(AF_INET, &addr, iaddr, iaddrlen) == NULL) {
syslog(LOG_ERR, "%s: inet_ntop: %m",
"get_nat_redirect_rule");
@ -619,7 +619,7 @@ get_nat_redirect_rule(const char * nat_chain_name, const char * ifname,
}
if (iport)
*iport = p->iport;
*iport = p->nat_port;
if(timestamp != NULL)
*timestamp = get_timestamp(eport, proto);
@ -659,8 +659,8 @@ get_portmappings_in_range(unsigned short startport, unsigned short endport,
LIST_FOREACH(p, &head_redirect, entry) {
if (p->proto == proto &&
startport <= p->eport &&
p->eport <= endport) {
startport <= p->dport &&
p->dport <= endport) {
if (*number >= capacity) {
capacity += 128;
@ -677,7 +677,7 @@ get_portmappings_in_range(unsigned short startport, unsigned short endport,
}
array = tmp;
}
array[*number] = p->eport;
array[*number] = p->dport;
(*number)++;
}
}

View File

@ -129,8 +129,8 @@ void
print_rule_t(const char *func, int line, const rule_t *r)
{
fprintf(stdout, "%s[%d]: ", func, line);
printf("%s %s %d %hu => %hu\n", r->table, r->chain, (int)r->type,
r->eport, r->iport);
printf("%s %s %d %hu => %hu => %hu\n", r->table, r->chain, (int)r->type,
r->sport, r->dport, r->nat_port);
}
/* print out the "filter" and "nat" tables */
@ -300,14 +300,9 @@ parse_rule_nat(struct nftnl_expr *e, rule_t *r)
}
reg_val_ptr = get_reg_val_ptr(r, addr_min_reg);
if (reg_val_ptr != NULL) {
if (r->nat_type == NFT_NAT_DNAT) {
r->iaddr = (in_addr_t)*reg_val_ptr;
r->iport = proto_min_val;
} else if (r->nat_type == NFT_NAT_SNAT) {
r->eaddr = (in_addr_t)*reg_val_ptr;
if (proto_min_reg == NFT_REG_1) {
r->eport = proto_min_val;
}
r->nat_addr = (in_addr_t)*reg_val_ptr;
if (proto_min_reg == NFT_REG_1) {
r->nat_port = proto_min_val;
}
} else {
syslog(LOG_ERR, "%s: invalid addr_min_reg %u", "parse_rule_nat", addr_min_reg);
@ -371,6 +366,9 @@ parse_rule_payload(struct nftnl_expr *e, rule_t *r)
if (offset == offsetof(struct tcphdr, dest) &&
len == sizeof(uint16_t)) {
*regptr = RULE_REG_TCP_DPORT;
} else if (offset == offsetof(struct tcphdr, source) &&
len == sizeof(uint16_t)) {
*regptr = RULE_REG_TCP_SPORT;
} else if (offset == offsetof(struct tcphdr, source) &&
len == sizeof(uint16_t) * 2) {
*regptr = RULE_REG_TCP_SD_PORT;
@ -428,44 +426,36 @@ parse_rule_cmp(struct nftnl_expr *e, rule_t *r)
break;
case RULE_REG_IP_SRC_ADDR:
if (data_len == sizeof(in_addr_t)) {
r->rhost = *(const in_addr_t *)data_val;
r->saddr = *(const in_addr_t *)data_val;
}
break;
case RULE_REG_IP6_SRC_ADDR:
if (data_len == sizeof(struct in6_addr)) {
r->rhost6 = *(const struct in6_addr *)data_val;
r->saddr6 = *(const struct in6_addr *)data_val;
}
break;
case RULE_REG_IP_DEST_ADDR:
if (data_len == sizeof(in_addr_t)) {
if (r->type == RULE_FILTER) {
r->iaddr = *(const in_addr_t *)data_val;
} else {
r->rhost = *(const in_addr_t *)data_val;
}
r->daddr = *(const in_addr_t *)data_val;
}
break;
case RULE_REG_IP6_DEST_ADDR:
if (data_len == sizeof(struct in6_addr)) {
if (r->type == RULE_FILTER) {
r->iaddr6 = *(const struct in6_addr *)data_val;
} else {
r->rhost6 = *(const struct in6_addr *)data_val;
}
r->daddr6 = *(const struct in6_addr *)data_val;
}
break;
case RULE_REG_IP_SD_ADDR:
if (data_len == sizeof(in_addr_t) * 2) {
const in_addr_t *addrp = (const in_addr_t *)data_val;
r->iaddr = addrp[0];
r->rhost = addrp[1];
r->saddr = addrp[0];
r->daddr = addrp[1];
}
break;
case RULE_REG_IP6_SD_ADDR:
if (data_len == sizeof(struct in6_addr) * 2) {
const struct in6_addr *addrp6 = (const struct in6_addr *)data_val;
r->iaddr6 = addrp6[0];
r->rhost6 = addrp6[1];
r->saddr6 = addrp6[0];
r->daddr6 = addrp6[1];
}
break;
case RULE_REG_IP_PROTO:
@ -474,16 +464,21 @@ parse_rule_cmp(struct nftnl_expr *e, rule_t *r)
r->proto = *(const uint8_t *)data_val;
}
break;
case RULE_REG_TCP_SPORT:
if (data_len == sizeof(uint16_t)) {
r->sport = ntohs(*(const uint16_t *)data_val);
}
break;
case RULE_REG_TCP_DPORT:
if (data_len == sizeof(uint16_t)) {
r->eport = ntohs(*(const uint16_t *)data_val);
r->dport = ntohs(*(const uint16_t *)data_val);
}
break;
case RULE_REG_TCP_SD_PORT:
if (data_len == sizeof(uint16_t) * 2) {
const uint16_t * ports = (const uint16_t *)data_val;
r->eport = ntohs(ports[0]);
r->rport = ntohs(ports[1]);
r->sport = ntohs(ports[0]);
r->dport = ntohs(ports[1]);
}
break;
default:

View File

@ -33,6 +33,7 @@ enum rule_reg_type {
RULE_REG_IP6_SD_ADDR, /* source & dest */
RULE_REG_IP_PROTO,
RULE_REG_IP6_PROTO,
RULE_REG_TCP_SPORT,
RULE_REG_TCP_DPORT,
RULE_REG_TCP_SD_PORT, /* source & dest */
RULE_REG_IMM_VAL, /* immediate */
@ -63,14 +64,14 @@ typedef struct rule_t {
uint32_t family;
uint32_t ingress_ifidx;
uint32_t egress_ifidx;
in_addr_t eaddr;
in_addr_t iaddr;
in_addr_t rhost;
struct in6_addr iaddr6;
struct in6_addr rhost6;
uint16_t eport;
uint16_t iport;
uint16_t rport;
in_addr_t saddr;
struct in6_addr saddr6;
uint16_t sport;
in_addr_t daddr;
struct in6_addr daddr6;
uint16_t dport;
in_addr_t nat_addr;
uint16_t nat_port;
uint8_t proto;
enum rule_reg_type reg1_type;
enum rule_reg_type reg2_type;

View File

@ -153,10 +153,10 @@ find_pinhole(const char * ifname,
if (p->desc_len == 0)
continue;
if ((proto == p->proto) && (rem_port == p->rport)
&& (0 == memcmp(&saddr, &p->rhost6, sizeof(struct in6_addr)))
&& (int_port == p->iport) &&
(0 == memcmp(&daddr, &p->iaddr6, sizeof(struct in6_addr)))) {
if ((proto == p->proto) && (rem_port == p->sport)
&& (0 == memcmp(&saddr, &p->saddr6, sizeof(struct in6_addr)))
&& (int_port == p->dport) &&
(0 == memcmp(&daddr, &p->daddr6, sizeof(struct in6_addr)))) {
if (sscanf(p->desc, PINEHOLE_LABEL_FORMAT_SKIPDESC, &uid, &ts) != 2) {
syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", p->desc);
@ -259,23 +259,23 @@ update_pinhole(unsigned short uid, unsigned int timestamp)
if (0 == strcmp(tmp_label, label_start)) {
/* Source IP Address */
// Check if empty
if (0 == memcmp(&rhost_addr, &p->rhost6, sizeof(struct in6_addr))) {
if (0 == memcmp(&rhost_addr, &p->saddr6, sizeof(struct in6_addr))) {
rhost_addr_p = NULL;
raddr[0] = '*';
raddr[1] = '\0';
} else {
rhost_addr_p = &p->rhost6;
rhost_addr_p = &p->saddr6;
inet_ntop(AF_INET6, rhost_addr_p, raddr, INET6_ADDRSTRLEN);
}
/* Source Port */
rport = p->iport;
rport = p->sport;
/* Destination IP Address */
ihost_addr = p->iaddr6;
ihost_addr = p->daddr6;
/* Destination Port */
iport = p->eport;
iport = p->dport;
proto = p->proto;
@ -357,23 +357,23 @@ get_pinhole_info(unsigned short uid,
if (0 == strcmp(tmp_label, label_start)) {
/* Source IP Address */
if (rem_host && (rem_host[0] != '\0')) {
if(inet_ntop(AF_INET6, &p->rhost6, rem_host, rem_hostlen) == NULL)
if(inet_ntop(AF_INET6, &p->saddr6, rem_host, rem_hostlen) == NULL)
return -1;
}
/* Source Port */
if (rem_port)
*rem_port = p->rport;
*rem_port = p->sport;
/* Destination IP Address */
if (int_client) {
if(inet_ntop(AF_INET6, &p->iaddr6, int_client, int_clientlen) == NULL)
if(inet_ntop(AF_INET6, &p->daddr6, int_client, int_clientlen) == NULL)
return -1;
}
/* Destination Port */
if (int_port)
*int_port = p->eport;
*int_port = p->dport;
if (proto)
*proto = p->proto;