Add support for nftables

This commit is contained in:
ppom 2024-02-05 12:00:00 +01:00
parent bfe0128764
commit bff697dc17
4 changed files with 110 additions and 9 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@
/deb /deb
*.deb *.deb
*.minisig *.minisig
*.qcow2

View File

@ -3,22 +3,24 @@ PREFIX ?= /usr/local
BINDIR = $(PREFIX)/bin BINDIR = $(PREFIX)/bin
SYSTEMDDIR ?= /etc/systemd SYSTEMDDIR ?= /etc/systemd
all: reaction ip46tables all: reaction ip46tables nft46
clean: clean:
rm -f reaction ip46tables reaction.deb deb reaction.minisig ip46tables.minisig reaction.deb.minisig rm -f reaction ip46tables reaction.deb deb reaction.minisig ip46tables.minisig reaction.deb.minisig
ip46tables: ip46tables.d/ip46tables.c ip46tables: helpers_c/ip46tables.c
$(CC) -s -static ip46tables.d/ip46tables.c -o ip46tables $(CC) -s -static helpers_c/ip46tables.c -o ip46tables
nft46: helpers_c/nft46.c
$(CC) -s -static helpers_c/nft46.c -o nft46
reaction: app/* reaction.go go.mod go.sum reaction: app/* reaction.go go.mod go.sum
CGO_ENABLED=0 go build -buildvcs=false -ldflags "-s -X main.version=`git tag --sort=v:refname | tail -n1` -X main.commit=`git rev-parse --short HEAD`" CGO_ENABLED=0 go build -buildvcs=false -ldflags "-s -X main.version=`git tag --sort=v:refname | tail -n1` -X main.commit=`git rev-parse --short HEAD`"
reaction.deb: reaction ip46tables reaction.deb: reaction ip46tables nft46
chmod +x reaction ip46tables chmod +x reaction ip46tables nft46
mkdir -p deb/reaction/usr/bin/ deb/reaction/usr/sbin/ deb/reaction/lib/systemd/system/ mkdir -p deb/reaction/usr/bin/ deb/reaction/usr/sbin/ deb/reaction/lib/systemd/system/
cp reaction deb/reaction/usr/bin/ cp reaction ip46tables nft46 deb/reaction/usr/bin/
cp ip46tables deb/reaction/usr/sbin/
cp config/reaction.debian.service deb/reaction/lib/systemd/system/reaction.service cp config/reaction.debian.service deb/reaction/lib/systemd/system/reaction.service
cp -r DEBIAN/ deb/reaction/DEBIAN cp -r DEBIAN/ deb/reaction/DEBIAN
sed -e "s/LAST_TAG/`git tag --sort=v:refname | tail -n1`/" -e "s/Version: v/Version: /" -i deb/reaction/DEBIAN/* sed -e "s/LAST_TAG/`git tag --sort=v:refname | tail -n1`/" -e "s/Version: v/Version: /" -i deb/reaction/DEBIAN/*
@ -26,12 +28,13 @@ reaction.deb: reaction ip46tables
mv deb/reaction.deb reaction.deb mv deb/reaction.deb reaction.deb
rm -rf deb/ rm -rf deb/
signatures: reaction.deb reaction ip46tables signatures: reaction.deb reaction ip46tables nft46
minisign -Sm ip46tables reaction reaction.deb minisign -Sm ip46tables nft46 reaction reaction.deb
install: all install: all
install -m755 reaction $(DESTDIR)$(BINDIR) install -m755 reaction $(DESTDIR)$(BINDIR)
install -m755 ip46tables $(DESTDIR)$(BINDIR) install -m755 ip46tables $(DESTDIR)$(BINDIR)
install -m755 nft46 $(DESTDIR)$(BINDIR)
install_systemd: install install_systemd: install
install -m644 config/reaction.debian.service $(SYSTEMDDIR)/system/reaction.service install -m644 config/reaction.debian.service $(SYSTEMDDIR)/system/reaction.service

97
helpers_c/nft46.c Normal file
View File

@ -0,0 +1,97 @@
#include<ctype.h>
#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
// nft46 'add element inet reaction ipvXbans { 1.2.3.4 }' → nft 'add element inet reaction ipv4bans { 1.2.3.4 }'
// nft46 'add element inet reaction ipvXbans { a:b::c:d }' → nft 'add element inet reaction ipv6bans { a:b::c:d }'
//
// the character X is replaced by 4 or 6 depending on the address family of the specified IP
//
// Limitations:
// - nft46 must receive exactly one argument
// - only one IP must be given per command
// - the IP must be between { braces }
int isIPv4(char *tab, int len) {
int i;
// IPv4 addresses are at least 7 chars long
if (len < 7 || !isdigit(tab[0]) || !isdigit(tab[len-1])) {
return 0;
}
// Each char must be a digit or a dot between 2 digits
for (i=1; i<len-1; i++) {
if (!isdigit(tab[i]) && !(tab[i] == '.' && isdigit(tab[i-1]) && isdigit(tab[i+1]))) {
return 0;
}
}
return 1;
}
int isIPv6(char *tab, int len) {
int i;
// IPv6 addresses are at least 3 chars long
if (len < 3) {
return 0;
}
// Each char must be a digit, :, a-f, or A-F
for (i=0; i<len; i++) {
if (!isdigit(tab[i]) && tab[i] != ':' && !(tab[i] >= 'a' && tab[i] <= 'f') && !(tab[i] >= 'A' && tab[i] <= 'F')) {
return 0;
}
}
return 1;
}
int findchar(char *tab, char c, int i, int len) {
while (i < len && tab[i] != c) i++;
if (i == len) {
printf("nft46: one %c must be present", c);
exit(1);
}
return i;
}
void adapt_args(char *tab) {
int i, len, X, startIP, endIP, startedIP;
X = startIP = endIP = -1;
startedIP = 0;
len = strlen(tab);
i = 0;
X = i = findchar(tab, 'X', i, len);
startIP = i = findchar(tab, '{', i, len);
while (startIP + 1 <= (i = findchar(tab, ' ', i, len))) startIP = i + 1;
i = startIP;
endIP = i = findchar(tab, ' ', i, len) - 1;
if (isIPv4(tab+startIP, endIP-startIP+1)) {
tab[X] = '4';
return;
}
if (isIPv6(tab+startIP, endIP-startIP+1)) {
tab[X] = '6';
return;
}
printf("nft46: no IP address found\n");
exit(1);
}
int exec(char *str, char **argv) {
argv[0] = str;
execvp(str, argv);
// returns only if fails
printf("nft46: exec failed %d\n", errno);
}
int main(int argc, char **argv) {
if (argc != 2) {
printf("nft46: Exactly one argument must be given\n");
exit(1);
}
adapt_args(argv[1]);
exec("nft", argv);
}