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;
> > }
> > //
> >
> -------------------------------------------------------------------------------------------------------
>

Reply via email to