Bug 188511 - [pf] [patch] divert-reply implementation for pf
Summary: [pf] [patch] divert-reply implementation for pf
Status: Open
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: Unspecified
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs (Nobody)
Depends on:
Reported: 2014-04-12 14:30 UTC by PiBa-NL
Modified: 2017-12-31 22:27 UTC (History)
0 users

See Also:

file.diff (2.88 KB, patch)
2014-04-12 14:30 UTC, PiBa-NL
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description PiBa-NL 2014-04-12 14:30:00 UTC
It is currently not possible to bind to a nonlocal ip and succesfully
connect a TCP socket.  This patch will include a new option for
pf 'divert-reply'.

This should work with the haproxy-devel port 'source usesrc
clientip' option.

But for easy testing i also include a python program that contacts a
webserver from a non-local ip using the IP_BINDANY or IPV6_BINDANY socket
option. A single firewall rule needs to be made that matches outbound
traffic, and has the divert-reply option. Like this:

"pass out  quick  on em0 inet proto tcp  from any to port 80 keep state divert-reply"

I hope this is OK and can be included in next release, if not please
let me know if and what to adjust.

I took pretty much all the code from here:

Adapted it to FreeBSD v10 , and removed the parts i was unable to test
(UDP and bridge support).

Fix: The attached patch.

Patch attached with submission follows:
How-To-Repeat: The python program below uses/demonstrates the function, make sure the
machine is in the return-path of the webserver traffic a.k.a. it is the
default route.

import socket
HOST = ''    # The remote host
PORT = 80              # The same port as used by the server
#s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#s.setsockopt(socket.IPPROTO_IP, 24,1) # IP_BINDANY=24 flag to allow binding to nonlocal sockets.

HOST = 'fd00:1::40'    # The remote host
PORT = 80              # The same port as used by the server
SOURCE = 'fd00:108::abcd'
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
s.setsockopt(41, 64,1) # IPV6_BINDANY=64 flag to allow binding to nonlocal sockets.

s.bind((SOURCE,0)) # port 0 so pick a random client port..
s.connect((HOST, PORT))
s.sendall('GET / HTTP/1.0\r\nhost: test\r\n\r\n')
x = 0
while True:
	data = s.recv(1024)
	x = x + len(data)
	if not data: break
	print repr(data)
print 'Received', repr(x), "bytes"
Comment 1 Mark Linimon freebsd_committer freebsd_triage 2014-04-16 02:38:05 UTC
Responsible Changed
From-To: freebsd-bugs->freebsd-pf

Over to maintainer(s).
Comment 2 Eitan Adler freebsd_committer freebsd_triage 2017-12-31 08:01:36 UTC
For bugs matching the following criteria:

Status: In Progress Changed: (is less than) 2014-06-01

Reset to default assignee and clear in-progress tags.

Mail being skipped