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