Basic transparent filtering with pf

Gerald McNulty gmnt99 at gmail.com
Fri Jan 6 03:22:41 UTC 2012


Hello,

I am trying to get a basic transparent proxy to work with pf under FreeBSD.
By "transparent", I mean that the client IP address is presented to the
destination server, not just that the proxy is accessed automatically
through rdr rules. The proxy is written in C and works correctly in
terminating the client -> proxy connection and the proxy -> server
connection with no user intervention.

Here is an example architecture, all IP addresses are valid routable, no
RFC1918.

client (100.100.100.5)  <->  (100.100.100.1 $int_if) router/proxy
(200.200.200.1 $ext_if) <--> {internet} <--> (50.50.50.50) server

Initial pf.conf lines:
  rdr pass on $int_if inet proto tcp from any to any -> $int_if port 7890
  pass in quick on $int_if
  pass in quick on $ext_if
  pass out keep state

Step 1:
Client initiates TCP connection to server. Proxy code on $int_if:7890
accept()'s connection, creates a new TCP connection between $ext_if and
server. This works as expected - the server sees 200.200.200.1 ($ext_if) as
the peer address while the client sees the true server's address
(50.50.50.50) as the peer

Step2:
Update the outbound connection request with a setsockopt(fd, IPPROTO_IP,
IP_BINDANY, &on, sizeof on)) and a bind() to the client's IP address
(100.100.100.5), correctly retrieved with ioctl(DIOCNATLOOK). Now connect.
The syn packet is sent, but the returning syn+ack is never answered and the
proxy socket never receives any data. A tcpdump from the proxy is below:

02:01:31.457764 IP 100.100.100.5.26023 > 50.50.50.50.http: Flags [S], seq
2436001586, win 65535, options [mss 1460,sackOK,eol], length 0
02:01:31.570653 IP 50.50.50.50.http > 100.100.100.5.26023: Flags [S.], seq
2750220640, ack 2436001587, win 65535, options [mss 1460,nop,wscale
3,sackOK,eol], length 0
02:01:34.569454 IP 50.50.50.50.http > 100.100.100.5.26023: Flags [S.], seq
2750220640, ack 2436001587, win 65535, options [mss 1460,nop,wscale
3,sackOK,eol], length 0
02:01:40.568830 IP 50.50.50.50.http > 100.100.100.5.26023: Flags [S.], seq
2750220640, ack 2436001587, win 65535, options [mss 1460,nop,wscale
3,sackOK,eol], length 0
02:01:43.656081 IP 100.100.100.5.26023 > 50.50.50.50.http: Flags [S], seq
2436001586, win 65535, options [mss 1460,sackOK,eol], length 0
02:01:43.768978 IP 50.50.50.50.http > 100.100.100.5.26023: Flags [S.], seq
2750220640, ack 2436001587, win 65535, options [mss 1460,nop,wscale
3,sackOK,eol], length 0
02:01:46.768123 IP 50.50.50.50.http > 100.100.100.5.26023: Flags [S.], seq
2750220640, ack 2436001587, win 65535, options [mss 1460,nop,wscale
3,sackOK,eol], length 0
02:01:52.767514 IP 50.50.50.50.http > 100.100.100.5.26023: Flags [S.], seq
2750220640, ack 2436001587, win 65535, options [mss 1460,nop,wscale
3,sackOK,eol], length 0
02:02:04.766253 IP 50.50.50.50.http > 100.100.100.5.26023: Flags [S.], seq
2750220640, ack 2436001587, win 65535, options [mss 1460,nop,wscale
3,sackOK,eol], length 0


Is this something that requires further pf rules? Or something in the C
code?

Any guidance would be much appreciated.

--
Gerald McNulty


More information about the freebsd-pf mailing list