Thanks Stuart.
I am going to look at rewriting it using pfctl for as much as possible
and go from there.
On 2018-05-11 07:08, Stuart Henderson wrote:
On 2018/05/10 17:18, Edward Lopez-Acosta wrote:
Hello,
I am working on porting sshuttle (https://github.com/sshuttle/sshuttle) to
OpenBSD and have run into some issues. Specifically issue #219, which is
due to "Operation not supported by device" errors.
https://github.com/sshuttle/sshuttle/issues/219
It looks to me like the memory address of the anchor data in pf may have
changed, though the first call to add a new anchor with "match any on lo"
seems to work ok.
For some reason the contributor wrote his Python script using ioctl and a
lot of C style code for the pf module. I was not able to reach him for
assistance with this either, and have been working on it for about a week
now.
I have the port made but holding off on submitting until this issue is
fixed. I was curious if anyone would be interested in this application, or
has any suggestions for fixing the pf module short of a full rewrite.
Thank you.
struct pfioc_rule itself hasn't changed format since 2004, but pf_rule
changes quite often.
The way it's done with structs and ioctls translated into Python
(https://github.com/sshuttle/sshuttle/blob/master/sshuttle/methods/pf.py)
really isn't good for us. When changes are made in the kernel/pfctl
interface a program that's doing (i.e. not tracking system headers)
is going to end up silently putting data in the wrong place with
who knows what effect.
We still have ports that haven't been updated to cope with PF changes
made years ago so I'm very reluctant to add anything else
which relies on fragile interfaces..
The usual advice is to use pfctl(8) as the interface. Which sshuttle
is partly doing and partly not.
There are a couple of parts to what it's doing, first in setup it's
(badly) trying to fix up an existing ruleset. This either needs
removing completely, or keep checks and just error out. Fixing up
existing user config like this on the fly cannot possibly work.
- Get rid of _add_anchor_rule
- Get rid of the bit where it replaces your entire ruleset with "match
on lo" if "set skip" isn't set how it wants...(aargh!).
(then there are supporting parts that can be removed too, things like
*_OFFSET which seem to only relate to _add_anchor_rule).
The second part is doing lookups for redirected connections which it's
doing with DIOCNATLOOK which does need to be done directly rather than
via pfctl.
The *preferred* way for looking up original addresses is to use divert-to
instead of rdr-to. This doesn't use DIOCNATLOOK at all, instead it's
retty much the same mechanism as Linux TPROXY - exact same for TCP,
UDP is a little different but still easy, IP_RECVDSTADDR/IPV6_RECVPKTINFO
and IP_RECVDSTPORT/IPV6_RECVDSTPORT instead of IP{V6,}_ORIGDSTADDR.
As well as being simpler and less racy, this also avoids the need for
privileged access to /dev/pf at runtime.
We mostly stopped using DIOCNATLOOK in base (there's one legacy mode
of relayd still using it) but a few ports are still using it, and the
structs involved are pretty stable (if I read correctly it hasn't
changed abi at all) so we could probably cope with having this in python
code if necessary.
However something looks wrong with their definition, we don't have a
"proto_variant" field in the struct, so if keeping the DIOCNATLOOK code
would need to figure out what's going on there.