PF pf nat rule for a specific user

Hi everyone,

I try to configure a pf nat rule which is only applied on a specific user. Is that possible? Because I always get a syntax error with the following rule:

Bash:
nat log on if1 from self to 1.2.3.4/32 user myuser -> 2.3.4.5

In the log message I can see that the uid is logged correctly, so I don't understand why this should not work.

Bash:
rule 1/0(match) [uid 555]: nat out on if1: 2.3.4.5.65243 > 1.2.3.4.80

The main goal is to change the source address for outgoing connections for that user.

Thank you in advance.
 
try to configure a pf nat rule which is only applied on a specific user. Is that possible?
Sort answer, no. User information isn't stored in an IP network packet. IP packets are the only thing the firewall sees. Hence it cannot differentiate between a packet that's created by user X or user Y because that information is simply not available.

Longer answer, yes. But this only works for processes that are running on the firewall host itself.

Code:
     user ⟨user⟩
           This rule only applies to packets of sockets owned by the specified
           user.  For outgoing connections initiated from the firewall, this
           is the user that opened the connection.  For incoming connections
           to the firewall itself, this is the user that listens on the
           destination port.  For forwarded connections, where the firewall is
           not a connection endpoint, the user and group are unknown.

           All packets, both outgoing and incoming, of one connection are
           associated with the same user and group.  Only TCP and UDP packets
           can be associated with users; for other protocols these parameters
           are ignored.

           User and group refer to the effective (as opposed to the real) IDs,
           in case the socket is created by a setuid/setgid process.  User and
           group IDs are stored when a socket is created; when a process
           creates a listening socket as root (for instance, by binding to a
           privileged port) and subsequently changes to another user ID (to
           drop privileges), the credentials will remain root.

           User and group IDs can be specified as either numbers or names.
           The syntax is similar to the one for ports.  The value unknown
           matches packets of forwarded connections.  unknown can only be used
           with the operators = and !=.  Other constructs like user ≥ unknown
           are invalid.  Forwarded packets with unknown user and group ID
           match only rules that explicitly compare against unknown with the
           operators = or !=.  For instance user ≥ 0 does not match forwarded
           packets.  The following example allows only selected users to open
           outgoing connections:

                 block out proto { tcp, udp } all
                 pass  out proto { tcp, udp } all user { < 1000, dhartmei }
 
Thank you for your reply. What I don't understand is that the uid is available in the log message. So that information is available, or am I wrong?

I already used that user option successfully for pass and block rules. One of my ideas was to tag the outgoing traffic before nat'ing and apply the nat rule on tagged packets. A nat rule could be applied for only specific tags, but I was unable to tag the outgoing traffic before nat'ing. I tried something like that:

Bash:
nat log on if1 from self to 1.2.3.4/32 tagged USER_myuser -> 2.3.4.5
 
packets originated on the nat host usually dont need nat because they bind to the ext_if when they go the internet

(unless you specifically tell them to bind on other address)
 
I'm aware of that. The thing is I need a specific outgoing IP address for that user and tried to achieve it like that.
 
Just to let you know I was able to implement the expected behaviour with IPFW:


Code:
$IPFW_CMD nat 1011 config ip 1.2.3.4
$IPFW_CMD add 01337 nat 1011 all from me to 8.8.8.8 uid myuser
$IPFW_CMD add 01338 nat 1011 all from not me to 1.2.3.4

(here just for traffic from myuser to 8.8.8.8)

But I'm still looking for the same solution for ipv6.
 
Back
Top