Solved PF: How can I limit the maximum number of connects to a jail?

Hi everybody, thank you for your time!

Can you help me to solve a question that follows me since some weeks.

Please have a look into my pf.conf. It's for FreeBSD 10.1-RELEASE. One SSH is listening to the host:22 and the next is listening to the jail:22 which is host:22000.

I limit the maximum number of connects to the host SSH to ten. Can I limit the number of connects to my jail to ten only by the use of PF? Not to mention both SSHs did work and my IP is not 1.2.3.4.

Code:
IF = "re0"
IP = "1.2.3.4"
NET = "1.2.3.4/24"

IFJAIL = "lo1"
IPJAIL = "10.0.0.1"
NETJAIL = "10.0.0.0/28"

PORTSSH = "22"
PORTSSHJAIL = "22000"

set block-policy drop
set skip on lo0

nat pass on $IF from $NETJAIL to any -> $IF
rdr pass on $IF proto tcp from any to $IP port $PORTSSHJAIL -> $IPJAIL port $PORTSSH

block in on $IF
block in on $IF proto tcp # not necessary
block in on $IF proto udp # not necessary
block in on $IF proto tcp from $NET # not necessary
block in on $IF proto udp from $NET # not necessary
pass in on $IF inet proto tcp from any to $IP port $PORTSSH flags S/SA synproxy state (max-src-conn 10)

block out on $IF
pass out on $IF inet proto udp from $IP to any modulate state
pass out on $IF inet proto tcp from $IP to any modulate state

Thanks again.
 
Last edited by a moderator:
Thanks for the response.

It actually limits the connects to SSH after rdr.

My interest is more specific: Can I limit the number of connects to a jail by the firewall PF before rdr?
I should have explained it more clear that SSH is just an example for any service and how the limitation can be done on host.
Can I gain a similar kind of limitation for the jails SSH (service)?
 
May I ask why you want to do this at firewall level? Limiting SSH to 10 concurrent connections will not stop the attackers. If you're concerned about SSH brute force attacks then you may want to consider using security/py-fail2ban to permanently ban attacker's ip addresses at firewall level by monitoring auth.log.
 
Thanks for the responses. It took me a little while to come back with a valuable answer.

Remington:
Indeed security/py-fail2ban can do it. Not by pf but it does.

gkontos:
Stateful tracking is done allready on host max-src-conn.
Your link directs to OpenBSD. Since a while pf on FreeBSD is a little different.
Especially with nat/rdr. But thanks to your idea I re-read:

pf.conf(5)

https://www.freebsd.org/cgi/man.cgi?query=pf.conf&sektion=5#TRANSLATION

Code:
...
Since translation occurs before filtering the filter engine will see packets as they look
after any addresses and ports have been translated. Filter rules will therefore have to filter
based on the translated address and port number. Packets that match a translation rule are
only automatically passed if the pass modifier is given, otherwise they are still subject to
block and pass rules.
...

I changed rdr pass to rdr to be able to place a filter rule and receive the same stateful tracking on jail which I get on host.

The following code is the result and working well:

Code:
IF = "re0"
IP = "1.2.3.4"
NET = "1.2.3.4/24"
IFJAIL = "lo1"
IPJAIL = "10.0.0.1"
NETJAIL = "10.0.0.1/28"
PORTSSH = "22"
PORTSSHJAIL = "22000"
set block-policy drop
set skip on lo0
nat pass on $IF from $NETJAIL to any -> $IF
rdr on $IF proto tcp from any to $IP port $PORTSSHJAIL -> $IPJAIL port $PORTSSH
block in all
pass in on $IF inet proto tcp from any to $IPJAIL port $PORTSSH flags S/SA keep state (max-src-conn 10)
pass in on $IF inet proto tcp from any to $IP port $PORTSSH flags S/SA synproxy state (max-src-conn 10)
pass out all

It is interesting that I have to use keep state on jail where I use synproxy state on host.
The synproxy state will anyway not be necessary on jail because ping is not default available on jail.

I consider this thread is solved. Agreed?

Thanks all.
 
Maybe I am an idiot but I use it in most of my host based firewalls. Never had a problem so far with IPv4. I remember though that it did not work with IPv6.
 
Back
Top