Thanks for your reply, I changed the rdr-to rule in the PF rules to divert-to, but when I try to connect from another computer, I get a "Connection refused" error, follow is the test step:
1. PF test rules on the openbsd box with IP 192.168.11.4: set skip on lo0 pass in quick log on em0 inet proto tcp to port 1234 \ divert-to 127.0.0.1 port 4000 pass out quick log inet \ divert-reply pass in pass out 2. Listen on tcp port 4000 on 192.168.11.4: $ nc -kl 4000 3. Connect from another host: $ nc 192.168.11.4 1234 (UNKNOWN) [192.168.11.4] 1234 (?): Connection refused Where did I go wrong? Thanks in advance . -- Xiang Bo On Sat, May 11, 2024 at 2:34 AM Stuart Henderson <s...@spacehopper.org> wrote: > Not directly answering about the change to DIOCNATLOOK (I don't know the > answer), but that's generally not recommended any more anyway - the > preferred option for transparent proxies is to use "divert-to" and then, > for TCP, getsockname(2), or for UDP, IP_RECVDSTADDR/IPV6_RECVDSTPORT > etc. In particular this is safer because you don't need access to > /dev/pf. > > On 2024/05/11 01:12, cut wave wrote: > > PF's DIOCNATLOOK system call can not obtain correct return data in > OpenBSD 7.3-7.5, but this > > call was normal before OpenBSD 7.3. I tested it on OpenBSD 7.2 and > OpenBSD 6.9 and both > > returned correct data. > > > > The test code is at the end of the report (from man page of PF with a > little modification), and > > the following is the test process: > > > > ### [Didn't WORK] DIOCNATLOOK didn't work on OpenBSD 7.3, the following > are systeminfo, pf > > rules and test process > > > > 1. os infomation > > openbsd# uname -a > > OpenBSD openbsd.home.pro 7.3 GENERIC.MP#5 amd64 > > > > 2. compile the test code > > openbsd# cc test.c > > > > 3. the pf rdr rule > > openbsd# pfctl -sr > > pass in quick on em0 inet proto tcp from any to any port = 1234 flags > S/SA rdr-to 127.0.0.1 > > port 4000 > > > > 4. connect from a client(192.168.11.74) to openbsd's port 1234, and > print the pf state table on > > openbsd. > > openbsd# pfctl -ss|grep 1234 > > all tcp 127.0.0.1:4000 (192.168.11.4:1234) <- 192.168.11.74:26244 > ESTABLISHED:ESTABLISHED > > > > 5. running test code with: client_ip client_port rdr_ip rdr_port, and > the code get an error > > message. > > openbsd# ./a.out 192.168.11.74 26244 127.0.0.1 4000 > > > > > a.out: DIOCNATLOOK: No such file or directory > > > > > > ### DIOCNATLOOK works on OpenBSD 7.2, the following are systeminfo, pf > rules and test process > > > > 1. os information > > obsd# uname -a > > OpenBSD obsd.my.domain 7.2 GENERIC.MP#758 amd64 > > > > 2. compile the test code > > openbsd# cc test.c > > > > 3. the pf rdr rule > > openbsd# pfctl -sr > > pass in quick on em0 inet proto tcp from any to any port = 1234 flags > S/SA rdr-to 127.0.0.1 > > port 4000 > > > > 4. connect from a client(192.168.11.74) to openbsd's port 1234, and > print the pf state table on > > openbsd. > > obsd# pfctl -ss | grep 1234 > > all tcp 127.0.0.1:4444 (192.168.11.43:1234) <- 192.168.11.74:38485 > FIN_WAIT_2:ESTABLISHED > > > > 5. running test code with: client_ip client_port rdr_ip rdr_port, and > the code get corrent > > result. > > obsd# ./a.out 192.168.11.74 38485 127.0.0.1 4444 > > internal host 192.168.11.43:1234 > > > > > > BTW: This code works on FreeBSD 14 and NetBSD 10 > > > > I looked at the source code of pf_ioctl.c and pf.c in both OpenBSD 7.2 > and OpenBSD 7.3, I > > noticed that the call changed from NB_FIND to NBT_FIND in OpenBSD 7.3, I > don't know if this is > > the cause. > > > > -- > > xiangbo > > > > Code of test.c: > > // > > > ------------------------------------------------------------------------------------------------------- > > #include <sys/types.h> > > #include <sys/socket.h> > > #include <sys/ioctl.h> > > #include <sys/fcntl.h> > > #include <net/if.h> > > #include <netinet/in.h> > > #include <net/pfvar.h> > > #include <err.h> > > #include <stdio.h> > > #include <stdlib.h> > > #include <string.h> > > > > u_int32_t > > read_address(const char *s) > > { > > int a, b, c, d; > > > > sscanf(s, "%i.%i.%i.%i", &a, &b, &c, &d); > > return htonl(a << 24 | b << 16 | c << 8 | d); > > } > > > > void > > print_address(u_int32_t a) > > { > > a = ntohl(a); > > printf("%d.%d.%d.%d", a >> 24 & 255, a >> 16 & 255, > > a >> 8 & 255, a & 255); > > } > > > > int > > main(int argc, char *argv[]) > > { > > struct pfioc_natlook nl; > > int dev; > > > > if (argc != 5) { > > printf("%s <client addr> <client port> <rdr addr> <rdr port>\n", > > argv[0]); > > return 1; > > } > > > > dev = open("/dev/pf", O_RDWR); > > if (dev == -1) > > err(1, "open(\"/dev/pf\") failed"); > > > > memset(&nl, 0, sizeof(struct pfioc_natlook)); > > nl.saddr.v4.s_addr = read_address(argv[1]); > > nl.sport = htons(atoi(argv[2])); > > nl.daddr.v4.s_addr = read_address(argv[3]); > > nl.dport = htons(atoi(argv[4])); > > nl.af = AF_INET; > > nl.proto = IPPROTO_TCP; > > nl.direction = PF_OUT; > > > > if (ioctl(dev, DIOCNATLOOK, &nl)) > > err(1, "DIOCNATLOOK"); > > > > printf("internal host "); > > print_address(nl.rdaddr.v4.s_addr); > > printf(":%u\n", ntohs(nl.rdport)); > > return 0; > > } > > // > > > ------------------------------------------------------------------------------------------------------- >