fix: skb->mark masks were multi-bit (IN mark matched OUT test) - transit traffic never reached the out ruleset; ingress/egress interface groups; pfctl resolves (egress) pool locally
This commit is contained in:
1 parent
c449e01b9a
commit
9c3c4b6bbc
3 files changed
+85
-3
No files matched your search
@@ -7,7 +7,7 @@
|
||||
long pfk_ioctl(struct file *f, unsigned int cmd, unsigned long addr);
|
||||
int pfk_enable(int on);
|
||||
void pfk_status(struct pf_status *s);
|
||||
#define PFK_SKIP_PF 0x50460040u /* skb->mark: reinjected, bypass pf */
|
||||
#define PFK_SKIP_PF 0x00000004u /* skb->mark: reinjected, bypass pf */
|
||||
|
||||
int pfk_hooks_register(void);
|
||||
void pfk_hooks_unregister(void);
|
||||
|
||||
@@ -35,8 +35,8 @@ struct pfk_pkt {
|
||||
int dir;
|
||||
};
|
||||
|
||||
#define PFK_DONE_IN 0x50460010u /* skb->mark bit: PF_IN pass completed */
|
||||
#define PFK_DONE_OUT 0x50460020u /* skb->mark bit: PF_OUT pass completed */
|
||||
#define PFK_DONE_IN 0x00000001u /* skb->mark bit: PF_IN pass completed */
|
||||
#define PFK_DONE_OUT 0x00000002u /* skb->mark bit: PF_OUT pass completed */
|
||||
|
||||
static void
|
||||
pfk_pkt_reinject(struct pfk_pkt *pk)
|
||||
|
||||
@@ -1562,6 +1562,84 @@ ifa_exists(const char *ifa_name)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PFLINUX: interface group emulation.
|
||||
*
|
||||
* OpenBSD creates the "ingress" and "egress" interface groups (ifgroups)
|
||||
* and pfctl expands "(egress)" in a pool into the addresses of the group
|
||||
* members via the SIOCGIFGMEMB socket ioctl. Linux has neither ifgroups
|
||||
* nor that ioctl, so resolve the two groups locally:
|
||||
*
|
||||
* egress -> the interface of the default route (the same interface the
|
||||
* kernel module marks as the pf "egress" interface)
|
||||
* ingress -> every non-loopback interface
|
||||
*/
|
||||
static struct node_host *
|
||||
ifa_group_members(const char *group, int flags)
|
||||
{
|
||||
struct node_host *n, *h = NULL, *c;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t slen = sizeof(sin);
|
||||
int s;
|
||||
|
||||
if (iftab == NULL)
|
||||
ifa_load();
|
||||
|
||||
if (!strcmp(group, "egress")) {
|
||||
/* source address of the default route */
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(9);
|
||||
sin.sin_addr.s_addr = htonl(0x01010101); /* discard route */
|
||||
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) != -1) {
|
||||
if (connect(s, (struct sockaddr *)&sin,
|
||||
sizeof(sin)) == 0 &&
|
||||
getsockname(s, (struct sockaddr *)&sin, &slen) == 0) {
|
||||
close(s);
|
||||
for (n = iftab; n; n = n->next) {
|
||||
if (n->af != AF_INET)
|
||||
continue;
|
||||
if (n->addr.v.a.addr.v4.s_addr !=
|
||||
sin.sin_addr.s_addr)
|
||||
continue;
|
||||
if ((c = calloc(1, sizeof(*c))) == NULL)
|
||||
err(1, "calloc");
|
||||
*c = *n;
|
||||
c->next = NULL;
|
||||
c->tail = c;
|
||||
return (c);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
close(s);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* "ingress" and any other group: every non-loopback interface */
|
||||
for (n = iftab; n; n = n->next) {
|
||||
if (n->af == AF_LINK)
|
||||
continue;
|
||||
if (n->ifa_flags & IFF_LOOPBACK)
|
||||
continue;
|
||||
if ((flags & PFI_AFLAG_BROADCAST) && n->af != AF_INET)
|
||||
continue;
|
||||
if ((c = calloc(1, sizeof(*c))) == NULL)
|
||||
err(1, "calloc");
|
||||
*c = *n;
|
||||
c->next = NULL;
|
||||
c->tail = c;
|
||||
if (h == NULL)
|
||||
h = c;
|
||||
else {
|
||||
h->tail->next = c;
|
||||
h->tail = c->tail;
|
||||
}
|
||||
}
|
||||
return (h);
|
||||
}
|
||||
|
||||
struct node_host *
|
||||
ifa_grouplookup(const char *ifa_name, int flags)
|
||||
{
|
||||
@@ -1576,6 +1654,10 @@ ifa_grouplookup(const char *ifa_name, int flags)
|
||||
strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name));
|
||||
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
|
||||
close(s);
|
||||
/* PFLINUX: interface group emulation (see above) */
|
||||
if (!strcmp(ifa_name, "ingress") ||
|
||||
!strcmp(ifa_name, "egress"))
|
||||
return (ifa_group_members(ifa_name, flags));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user