IPF ipf use dhcp/pppoe interface ip in ruleset

Hello,

i am setting up a bsd router with ipfilter.
My external network is on em0 with pppoe and an dynamic ip address via pppoe/dhcp.
I already checked the manual but i could not find an predefined variable to get the interface IP in a ipf rule set.

With a static wan IP i would create a rule like this
pass in log quick on em0 proto tcp from 1.2.3.4 to 77.18.22.78 port = 22 flags S keep state

But as this is a normal DSL Connection my wan address keeps changing. So i need a way to automatic update the interface IP in the rule set.
pass in log quick on em0 proto tcp from 1.2.3.4 to em0.ip port = 22 flags S keep state
Is there a way to achieve this ?

Best regards
 
Why not,

pass in log quick on em0 proto tcp from 1.2.3.4 to any port = 22 flags S/SAFR keep state

I'm on a cable connection. The IP changes about 2-3 times a year. One of my ssh rules is:

pass in quick on sk1 family inet proto tcp from hash/provider-net to any port = 22 flags S/SAFR keep state keep frags

I don't need the destination address because, whatever it is, it's always my sk1 interface connected to the cable modem. Neither do you need the destination address because whatever it is, it's always the em0 interface on your firewall.

BTW, the hash/providfer-net is an ippool(5) hash table of IP addresses. provider-net is the name of the hash table.
 
In IPFW ipfw(8) there's "me" which refer to all local ip addresses on all interfaces of the local host.
ipfw add allow tcp from any to me setup limit src-addr 4

In ipfilter ipf(5) there's netmask on interface like this
pass in on bge0 proto icmp from any to bge0/netmasked

I primary use pf pf.conf(5) or ipfw(8) and i'm not familiar with ipf so my recommendation is to use the firewall that you understand. All of them will do the job.
 
Last edited:
Hi VladiBG,

this looks very promissing
so if i get this right my rule would looke like this :
pass in log quick on em0 proto tcp from 1.2.3.4 to em0/netmasked port = 22 flags S keep state

For the first test this seems to be working :)
Thank you.

I will have to do some more testing as i face some other wired behaviour in rule evaluation in combination with policy based IPSec. But for this i will propably create another post.

Thank you very much.
 
Hi VladiBG,

i testet a bit and this does not seem to work ...


pass in quick on $wan proto tcp from {1.2.3.4 5.6.7.8} to $wan/netmasked port = 22 flags S/SAFT keep state
pass in quick on $wan proto udp from 1.2.3.4 to $wan/netmasked port = 500
pass in quick on $wan proto udp from 1.2.3.4 to $wan/netmasked port = 4500
pass in quick on $wan proto esp from 1.2.3.4 to $wan/netmasked


When i apply this i get the following error :


ipf -Fa -f /etc/ipf.rules
24:25:ioctl(add/insert rule): bad interface index with dynamic dest. address


What am i doing wrong ?
 
SurtursRevenge cy@
Is there any particular reason to use IPF (looks like an abandoned software to me), why not pick PF instead which is its brother (syntax is almost the same) or even IPFW which is still receiving a bit of love.
This is not criticism I am just trying to understand your choice.
 
SurtursRevenge cy@
Is there any particular reason to use IPF (looks like an abandoned software to me), why not pick PF instead which is its brother (syntax is almost the same) or even IPFW which is still receiving a bit of love.
This is not criticism I am just trying to understand your choice.
I maintain it. Like FreeBSD pf is significantly different from OpenBSD pf because we maintain it (OpenBSD is no longer our pf upstream), ipf is significantly different than what it once was. I've made a lot of changes to it. This is why I moved it (suggested by glebius) from sys/contrib to sys/netpfil. We are the ipf upstream now.

Also sending patches to NetBSD as necessary. And illumos has expressed interest in receiving our updates to their ipf, replacing their 4.1.8 with our 5.1.2 + our patches -- though they want zone support and we have jail support.

More updates to ipf are coming. I will rewrite radix_ipf after I replace Heimdal with MIT in base. After that I want to bring in support similar to Linux iptables MSS blocking and MSS clamping.

Remember, we are the ipf upstream now since I moved ipf to netpfil and all the extra patches I've applied. (Similar situation to our pf relationship to OpenBSD pf. We can never import a new OpenBSD pf because that would case significant regressions.)
 
cy@ ipf is not ipfw, correct? I just need to go back through my documentation.
Correct.

ipfw is the native FreeBSD packet filter. It probably predates ipfilter.

ipfilter was imported at the time because it had more features than ipfw. Since then the missing features were added to ipfw, and some.

ipfilter at the time supported virtually every UNIX-like system on the planet, including Linux. I have removed all support from all other O/Ss in our ipfilter, except for NetBSD and Solaris because we currently exchange code with NetBSD and illumos has expressed interest in importing the FreeBSD ipfilter into illumos to upgrade their 4.1.8 to 5.1.2 + FreeBSD patches. I have additional plans for ipfilter in my pipeline.

pf was imported from OpenBSD. They created pf because of ipfilter licensing at the time, which was subsequently resolved to BSD for all the BSDs. (Licensing was changed for all non-BSD systems so that ipfilter could be imported into Solaris. Darren Reed landed a job at Sun Microsystems at the time.) But too late, OpenBSD removed ipfilter over a weekend. They quickly wrote their own within a few weeks.

pf was imported into FreeBSD and subsequently heavily modified to support SMP, among other things. OpenBSD has refused to accept FreeBSD modifications or SMP support. Importing a new OpenBSD pf is out of the question. It would remove our SMP support and all other modifications to FreeBSD pf. FreeBSD pf and OpenBSD pf are no longer the same.

A few years ago NetBSD developed their own pf from scratch, calling it npf. The NetBSD npf is not in FreeBSD.

Different FreeBSD developers maintain the different packet filtrers in FreeBSD.
 
Very interesting answer cy@ thank you!

Needed to dig a bit on what is 'MSS' but I get it (I've learned few things today).
Now I finally understand why IllumOS(OmniOS more specifically) runs IPF as primary firewall which to me was a total mystery because other than being available via pkgsrc I could not find a reason, they don't have to handle the development nor the maintenance because FreeBSD does it, thanks to you then. Do you maintain it alone?

What made you involved in IPF rather than PF, I mean PF being a fork from IPF both are very similar except than PF is way more popular now than any other firewall in FreeBSD IPFW included, so for me IPF was kind of abandoned at least I thought that (it doesn't even have a slot in mailing lists), so I have to ask, is it because of a functionality, concept, logic that you miss, or just because you like it better for other reason?

Quick remark, what I like about it is all the reading in examples directory:
Code:
~ : ll /usr/share/examples/ipfilter/
total 218
-r--r--r--  1 root  wheel   3,9K 12 mai    2022 BASIC_1.FW
-r--r--r--  1 root  wheel   2,5K 12 mai    2022 BASIC_2.FW
-r--r--r--  1 root  wheel   1,6K 12 mai    2022 BASIC.NAT
-r--r--r--  1 root  wheel   133B 12 mai    2022 example.1
-r--r--r--  1 root  wheel   431B 12 mai    2022 example.10
-r--r--r--  1 root  wheel   820B 12 mai    2022 example.11
-r--r--r--  1 root  wheel   376B 12 mai    2022 example.12
-r--r--r--  1 root  wheel   468B 12 mai    2022 example.13
-r--r--r--  1 root  wheel   2,0K 12 mai    2022 example.14
-r--r--r--  1 root  wheel   149B 12 mai    2022 example.2
-r--r--r--  1 root  wheel   990B 12 mai    2022 example.3
-r--r--r--  1 root  wheel    66B 12 mai    2022 example.4
-r--r--r--  1 root  wheel   689B 12 mai    2022 example.5
-r--r--r--  1 root  wheel   186B 12 mai    2022 example.6
-r--r--r--  1 root  wheel   362B 12 mai    2022 example.7
-r--r--r--  1 root  wheel   326B 12 mai    2022 example.8
-r--r--r--  1 root  wheel   291B 12 mai    2022 example.9
-r--r--r--  1 root  wheel   2,0K 12 mai    2022 example.sr
-r--r--r--  1 root  wheel    18K 12 mai    2022 examples.txt
-r--r--r--  1 root  wheel   1,5K 12 mai    2022 firewall
-r--r--r--  1 root  wheel   1,4K 12 mai    2022 firewall.1
-r--r--r--  1 root  wheel   3,0K 12 mai    2022 firewall.2
-r--r--r--  1 root  wheel   1,2K 12 mai    2022 ftp-proxy
-r--r--r--  1 root  wheel   272B 12 mai    2022 ftppxy
-r--r--r--  1 root  wheel   112K 10 juil.  2023 ipf-howto.txt
-r--r--r--  1 root  wheel   1,2K 12 mai    2022 ipf.conf.permissive
-r--r--r--  1 root  wheel   4,0K 12 mai    2022 ipf.conf.restrictive
-r--r--r--  1 root  wheel   783B 12 mai    2022 ipf.conf.sample
-r--r--r--  1 root  wheel   126B 12 mai    2022 ipnat.conf.sample
-rwxr-xr-x  1 root  wheel   2,6K 12 mai    2022 mkfilters*
-r--r--r--  1 root  wheel   2,8K 12 mai    2022 nat-setup
-r--r--r--  1 root  wheel   596B 12 mai    2022 nat.eg
-r--r--r--  1 root  wheel   374B 12 mai    2022 README
-r--r--r--  1 root  wheel   5,1K 12 mai    2022 rules.txt
-r--r--r--  1 root  wheel   471B 12 mai    2022 server
-r--r--r--  1 root  wheel   453B 12 mai    2022 tcpstate
 
I mean PF being a fork from IPF
Nothing I say here is authoritative, just what I've found/seen about pf/ipf.
I may be wrong but everything I've read indicates pf sprung up independently in OpenBSD because of a licensing issue.

"The Book Of pf" by Peter Hansteen has something about Darren Reed saying IPFilter was not BSD licensed back in 2001 (OpenBSD 2.x timeframe) That resulted in Daniel Hartmeirer and others creating pf for OpenBSD 3.0.
The version of IPFilter in OpenBSD at that time had lots of modifications and a reading of the license said/implied "can't modify".

We all know how much OpenBSD/Theo care about licensing so I can accept/believe something like this happening.

Perhaps it was a misunderstanding, perhaps it was clarified, perhaps it was correct. I don't know,
 
pf is not an ipf fork. It's a brand new firewall. Theo & co. didn't want to be encumbered by GPL when Darren briefly changed the license to GPL, which was changed back to BSD for the *BSD operating systems. I have an email from Darren, imported into the ipf vendor branch, that gives FreeBSD, specifically, BSD license. I think OpenBSD should have waited a bit for the dust to settle before ripping it out and building their own. FreeBSD and NetBSD waited for the dust to settle and we got BSD licensing.

I do most of the work with ipfilter though other people commit. I 'm the primary maintainer. I have a shopping list of things to do when I get more time after the MIT import. That project has consumed most of my FreeBSD time lately.

I have a hypothesis as to why pf is more popular. People tend to think that because OpenBSD's focus is security that it must be more secure. I'm of the opinion that FreeBSD is just as secure as OpenBSD.

I got involved with ipfilter long before pf ever existed. I've been using ipfilter since the 1990s, installing it on Solaris at $((JOB-1)) and installing newer versions on FreeBSD before FreeBSD did. That was long before I got my commit bit. $((JOB-1)) used it quite extensively. It made more sense to me to use ipfilter on Solaris and FreeBSD, using the same infrastructure of makefiles and rdist to manage my network, documenting the simplified approach for the team I led.

So yeah, ipfitler was light years ahead of ipfw for features at the time while pf didn't even exist then.

Talking about licensing changes. This is why we have OpenSSH. The folks at ssh.com changed their licensing. OpenBSD forked SSH1 to implemenent OpenSSH with SSH2 support. This is not what they did with pf. They wrote that from scratch.

Yeah, the examples are quite handy. I should add to them. There is an example in the original source that shows how to compile rules into ipfilter. It's been a while since I've looked at that but it would certainly be useful in an embedded environment where rules cannot be updated or replaced.
 
Thanks cy@ Your first paragraph is basically what I've gleaned through the years; the last sentence of the second paragraph I agree with.

If one starts with the assumption of "the firewall will work" you wind up at "how to specify what the firewall will do"; basically the syntax.
Simplistically, I think the syntax always falls into "first match wins" or "last match wins". Both work, a user just has to adjust their mindset. I don't know if either way is more efficient as long as the ruleset is defined correctly.

Knowing how to actually think about your network and define "deny this, pass that" I think is more important than the actual firewall product being used.
 
  • Like
Reactions: cy@
ipfilter and pf support "first match wins" with the quick keyword. Otherwise both default to "last match wins." I use both.

ipfw is like iptables, supporting only "first match wins."

Agreed, it doesn't matter which firewall you use, as long as it works. And, as long as one is happy with it. Understanding the network and the basics of TCP/IP is a must or the network will go sideways. Seen too many professional firewall admins get in way too over their head this way.
 
ipfilter and pf support "first match wins" with the quick keyword. Otherwise both default to "last match wins." I use both.
This is the primary reason that pf made sense to me. Start with "default deny, no quick" then add in "allow this" for me made easier to understand rulesets.

Your last paragraph, way too true.
 
Ok so i tested now


re0/netmasked
{re0/netmasked}
$wan/netmasked
{$wan/netmasked}


none of them work ... All give me the same error
 
SurtursRevenge cy@
Is there any particular reason to use IPF (looks like an abandoned software to me), why not pick PF instead which is its brother (syntax is almost the same) or even IPFW which is still receiving a bit of love.
This is not criticism I am just trying to understand your choice.
I choose ipf because of it flexible configuration and zone support. I want and need to specify the paket flow exactly by source and dest ip and by inbound and outbound interface / zone.
When i decided to go with ipf i compared it to ipfw and pf and ipf was the clear winner for me as it fulfills all my requirements.
But the reasy why i choose ipf is maybe a bit out of scope of this thread.
 
Here is the complete dump of my testing ruleset.
Maybe this helps


# Variables
wan="re0";
mgmt="re1.7";
guest="re1.253";

# no restrictions on loopback interface
pass in quick on lo0 all
pass out quick on lo0 all


# Rules
pass in log quick proto icmp keep state
pass in quick on $wan proto tcp from {1.2.3.4 5.6.7.8} to $wan/netmasked port = 22 flags S/SAFR keep state
pass in quick on $wan proto udp from 1.2.3.4 to $wan/netmasked port = 500
pass in quick on $wan proto udp from 1.2.3.4 to $wan/netmasked port = 4500
pass in quick on $wan proto esp from 1.2.3.4 to $wan/netmasked
pass in log quick on {$guest $mgmt} proto tcp from any to any port = 53 flags S/SAFR keep state
pass in log quick on {$guest $mgmt} proto udp from any to any port = 53

# VPN

pass in log quick proto tcp from 192.168.178.20 to 10.111.7.0/24 port = 22 flags S/SAFR keep state


# Outbound Internet
pass in log quick on $guest out-via $wan proto tcp from any to any flags S/SAFR keep state
pass in log quick on $guest out-via $wan proto udp from any to any
pass in log quick on $guest out-via $wan proto icmp from any to any


# Cleanup Rule
block in log all
pass out log all
 
Nothing I say here is authoritative, just what I've found/seen about pf/ipf.
I may be wrong but everything I've read indicates pf sprung up independently in OpenBSD because of a licensing issue.
pf is not an ipf fork. It's a brand new firewall. Theo & co. didn't want to be encumbered by GPL when Darren briefly changed the license to GPL, which was changed back to BSD for the *BSD operating systems. I have an email from Darren, imported into the ipf vendor branch, that gives FreeBSD, specifically, BSD license. I think OpenBSD should have waited a bit for the dust to settle before ripping it out and building their own. FreeBSD and NetBSD waited for the dust to settle and we got BSD licensing.
You guys are right I've got confused, thank you to point that out.
I think the similar syntax both have leads me to that wrong conclusion.

I got involved with ipfilter long before pf ever existed. I've been using ipfilter since the 1990s, installing it on Solaris at $((JOB-1)) and installing newer versions on FreeBSD before FreeBSD did. That was long before I got my commit bit. $((JOB-1)) used it quite extensively. It made more sense to me to use ipfilter on Solaris and FreeBSD, using the same infrastructure of makefiles and rdist to manage my network, documenting the simplified approach for the team I led.
You are long-time user, this answers most of the questions I had, it makes sense I understand the reasoning.

I do most of the work with ipfilter though other people commit. I 'm the primary maintainer. I have a shopping list of things to do when I get more time after the MIT import. That project has consumed most of my FreeBSD time lately.
While I've read some of the txt files in the examples directory I mentioned before I am not yet an IPF user but thank you for your work!
I'll learn it when I'll be ready to play more with IllumOS/OmniOS I guess because of the zones.

I choose ipf because of it flexible configuration and zone support. I want and need to specify the paket flow exactly by source and dest ip and by inbound and outbound interface / zone.
When i decided to go with ipf i compared it to ipfw and pf and ipf was the clear winner for me as it fulfills all my requirements.
But the reasy why i choose ipf is maybe a bit out of scope of this thread.
Thank you for your answer, it's interesting to know the reasons that lead a user to pick a software more than another, it helps to understand the beast.
Sorry if I hijacked your thread, this kind of topic is rare (having a user and a dev) that I took my chance, I leave it to you now, thank you.
 
Here is the complete dump of my testing ruleset.
Maybe this helps


# Variables
wan="re0";
mgmt="re1.7";
guest="re1.253";

# no restrictions on loopback interface
pass in quick on lo0 all
pass out quick on lo0 all


# Rules
pass in log quick proto icmp keep state
pass in quick on $wan proto tcp from {1.2.3.4 5.6.7.8} to $wan/netmasked port = 22 flags S/SAFR keep state


So far so good.


pass in quick on $wan proto udp from 1.2.3.4 to $wan/netmasked port = 500
pass in quick on $wan proto udp from 1.2.3.4 to $wan/netmasked port = 4500
pass in quick on $wan proto esp from 1.2.3.4 to $wan/netmasked


How are replies to egress unless there is either keep state or a corresponding egress rule?


pass in log quick on {$guest $mgmt} proto tcp from any to any port = 53 flags S/SAFR keep state


This is fine.


pass in log quick on {$guest $mgmt} proto udp from any to any port = 53


Again, where is the egress rule or keep state?


# VPN

pass in log quick proto tcp from 192.168.178.20 to 10.111.7.0/24 port = 22 flags S/SAFR keep state


This is fine.


# Outbound Internet
pass in log quick on $guest out-via $wan proto tcp from any to any flags S/SAFR keep state
pass in log quick on $guest out-via $wan proto udp from any to any
pass in log quick on $guest out-via $wan proto icmp from any to any


Why pass in on your internal interface? Why not pass out on the external interface?

Then use keep state on udp and icmp. ipfilter (and other firewalls, including commercial firewalls) set a timer to allow stateless protocols to mimic state.


# Cleanup Rule
block in log all
pass out log all


I tend to put these first.

My ipfilter recommendations would also apply to pf, or any other firewall.
 
Hi cy@

How are replies to egress unless there is either keep state or a corresponding egress rule?
Fair Point. I think i got this wrong, as i tought UDP is stateless. Would "keep state" on the UDP rule be enough ? Or do i have to also use flags. At the moment the egress should be handled by "pass out all", but you are right, making this "statefull" is the cleaner way to go. I will update this.

But still
re0/netmasked
24:25:ioctl(add/insert rule): bad interface index with dynamic dest. address
Do you have an idear what is wrong here ?

# VPN

pass in log quick proto tcp from 192.168.178.20 to 10.111.7.0/24 port = 22 flags S/SAFR keep state


This is fine.
This is not working at the moment ... I am pulling my hair out. I use Strongswan policy based IPSec. So the route to the remote network points to re0, which is the wan interface. I think this is how strongswan works. In the packet log i see blocks on the "answer" packet from 10.111.7.1 -> 192.168.178.20. Do you have a clue, why the answer is blocked, even i have set the keep state ?

pass in log quick on $guest out-via $wan proto icmp from any to any


Why pass in on your internal interface? Why not pass out on the external interface?
Why not ? What would be the benefits or the draw backs.
Having a Check Point background it seems natural to me to block the packet at earliest stage possible, which is when the packet enters a interface.
Also this seems to be easier to me for handling. Otherwhise there would be a pass in all and then you need to be carefull with ipsec vpn where the networks not have a physical interface they leave. So for my usecase i think it is much more easy to go with the pass in way. Or am i missing a major drawback ?


Then use keep state on udp and icmp. ipfilter (and other firewalls, including commercial firewalls) set a timer to allow stateless protocols to mimic state.
Ok fair. I will add this. Can i fine tune these timers ? Idealy per rule or are they global ?


# Cleanup Rule
block in log all
pass out log all


I tend to put these first.
Any particular reason ? As these rules are last match logicaly the make sense at the end for me. But this should'n make any difference as quick rules are evalueted beforce. Am i right ?
 
Hi cy@


Fair Point. I think i got this wrong, as i tought UDP is stateless. Would "keep state" on the UDP rule be enough ? Or do i have to also use flags. At the moment the egress should be handled by "pass out all", but you are right, making this "statefull" is the cleaner way to go. I will update this.

But still

Do you have an idear what is wrong here ?

pass in udp keep state is handled by timer. The default UDP timeout is 240 seconds.

This is not working at the moment ... I am pulling my hair out. I use Strongswan policy based IPSec. So the route to the remote network points to re0, which is the wan interface. I think this is how strongswan works. In the packet log i see blocks on the "answer" packet from 10.111.7.1 -> 192.168.178.20. Do you have a clue, why the answer is blocked, even i have set the keep state ?

You can use keep state with other IP protocols. ip_timeout would apply. Though, with IPsec I'd personally use a pass in and a separate pass out rule on the external interface.

Why not ? What would be the benefits or the draw backs.

The real question is, why are you putting the rule on the internal interface?

Having a Check Point background it seems natural to me to block the packet at earliest stage possible, which is when the packet enters a interface.

If you're blocking internal packets from egress, you could block internally but you still need a keep state on the external interface. Else the block on the external interface will block it before the state table is referenced on the internal interface.
 
Hi cy@

You can use keep state with other IP protocols. ip_timeout would apply. Though, with IPsec I'd personally use a pass in and a separate pass out rule on the external interface.
Not shure if i get this right

#this allows enrypted ipsec traffic
pass in quick on $wan proto udp from 1.2.3.4 to any port = 500 keep state
pass in quick on $wan proto udp from 1.2.3.4 to any port = 4500 keep state
pass in quick on $wan proto esp from 1.2.3.4 to any keep state

# this allows clear traffic "into" the VPN
pass in log quick proto tcp from 192.168.178.20 to 10.111.7.0/24 port = 22 flags S/SAFR keep state

But why is the decrypted answer packet the blocked as shown in the log ?
pass out log all
All egress packets should be allowed and the state should be keeped. I don't get this.


The real question is, why are you putting the rule on the internal interface?
What would be the benefits in putting the rules on the external interface ? Where would be the difference ?
Also how would this work on vpn as it does not have a interface ?


pass in log quick on $clients proto tcp from 10.111.9.0/24 to 192.168.178.10 port = 445 flags S/SAFR keep state
pass in log quick on $clients proto tcp from 10.111.9.0/24 to 192.168.178.2 port = 3389 flags S/SAFR keep state

What i now do is having pass in on the client interface and allowing to access a file server and a terminal server. How would you do this ?


So i want the clients to connect to the internet and the vpn. and like guests only to have access to the internet

# Guest
pass in log quick on $guest out-via $wan proto tcp from any to any flags S/SAFR keep state
pass in log quick on $guest out-via $wan proto udp from any to any keep state
pass in log quick on $guest out-via $wan proto icmp from any to any keep state

Thats why i use pass in and out via to ensure the packet uses the correct path. Or did i get something wrong here ?

If you're blocking internal packets from egress, you could block internally but you still need a keep state on the external interface. Else the block on the external interface will block it before the state table is referenced on the internal interface.
Shouldn't these internal egress packets be allowed because of
pass out log all

What is also a bit strange.
I have a client with dhcp IP 10.111.9.119. The Client Interface on the Router is 10.111.9.254. Why can the Client access the router via ssh on 10.111.9.254. There is no pass rule allowing this an a
block in log all rule that should prohibit this.
So what is the herarchy of the rules and why isn't this access blocked ?


Also do you have any idear why re0/netmasked gives me the "24:25:ioctl(add/insert rule): bad interface index with dynamic dest. address" ?
 
Back
Top