DaemonForums  

Go Back   DaemonForums > OpenBSD > OpenBSD Security

OpenBSD Security Functionally paranoid!

Reply
 
Thread Tools Display Modes
  #1   (View Single Post)  
Old 31st December 2024
mefisto mefisto is offline
Shell Scout
 
Join Date: Sep 2017
Posts: 110
Default OpenBSD firewall/router, almost there, but . . .

I still have a problem.

I had been sharing a network with my landlord, but for various reasons we needed to split it. I acquired another address and separated my network. The issue is that we bought together a printer, which remains on his (flat) network with IP addresses 192.168.0.1/24.

My network currently looks like this:
Code:
#---------------------------------#
# Macros
#---------------------------------#

# Interfaces
# Externa interface
ext_if="igc0"

# VLANs interfaces
vlan_1="igc1"
vlan_3="igc3"
the idea being that I have the DHCP server from the 192.168.0.1/24 assign me an address on the vlan_3.

For that I have in /etc/rc.conf.local
Code:
dhcp_flags=igc1
to prevent assignment from my DHCP server on igc3 interface and in /etc/hostname.igc3
Code:
inet autoconf
However the /etc/pf.conf cannot be loaded because the system cannot parse host specification
Code:
pass in on vlan_1:network to $vlan_3
As best as I can understand, the reason is that no address is assigned -at the time of loading the rules - to the igc3 interface.

Questions:
1 Is my approach to connect the two networks to reach the printer reasonable?
2. If so, what is my problem with not loading the rules, and how to solve it?

Kindest regards,

M
Reply With Quote
  #2   (View Single Post)  
Old 31st December 2024
jggimi's Avatar
jggimi jggimi is offline
More noise than signal
 
Join Date: May 2008
Location: USA
Posts: 8,099
Default

Do you have a typo in your post? I don't think the variable "dhcp_flags" is is correct. You might have meant "dhcpd_flags", for provisioning the dhcpd(8) daemon.

In PF, the interface modifier ":network" is defined as all of the addresses of all of the subnets provisioned on the specified interface. The pf.conf(5) man page explains why the rule fails, and also, explains how to change the rule for dynamic networks:
Quote:
Host name resolution and interface to address translation are
done at ruleset load-time. When the address of an interface (or
host name) changes (under DHCP or PPP, for instance), the ruleset
must be reloaded for the change to be reflected in the kernel.
Surrounding the interface name (and optional modifiers) in
parentheses changes this behaviour. When the interface name is
surrounded by parentheses, the rule is automatically updated
whenever the interface changes its address.
Reply With Quote
  #3   (View Single Post)  
Old 31st December 2024
mefisto mefisto is offline
Shell Scout
 
Join Date: Sep 2017
Posts: 110
Default

Hi jggimi,

yes, it is a typo, the /etc/rc.conf.local has the correct dhcpd_flags.

Yes, I understand the treatment of the dynamically changing interface, in fact,I have such a rule for $ext_if. However, when I was experimenting with the $vlan_3 to ensure that routing worked I assigned it a fixed address, and then forgot about the rule. Typical moron(tm).

Kindest regards,

M
Reply With Quote
  #4   (View Single Post)  
Old 31st December 2024
jggimi's Avatar
jggimi jggimi is offline
More noise than signal
 
Join Date: May 2008
Location: USA
Posts: 8,099
Default

Another option to consider is using the interface without the :network modifier, which will match all inbound traffic arriving via $vlan_1, regardless of originating address.
Reply With Quote
  #5   (View Single Post)  
Old 31st December 2024
mefisto mefisto is offline
Shell Scout
 
Join Date: Sep 2017
Posts: 110
Default

Hi jggimi,

thank you again for your additional advice.

Obviously, I have some difficulty understanding the man-pages. From pf.conf man-page (emphasis supplied):
Code:
:network    Translates to the network(s) attached to the interface.
As I interpret it, if a packet arrives at the interface from outside (the "translates to) and addresses any member device of the network, the packet will be accepted. But, this interpretation does seem to correlate with yours.

In that regard, I have difficulty interpret the in and out directives. Again, from the pf.conf:
Code:
in or out     A packet always comes in on, or goes out through, one interface. in and out apply to incoming and outgoing packets; if neither are specified, the rule will match packets in both directions.
Let us take the external interface. The in can be considered as packets arriving in from the outside and going out into the attached devices, or arriving in from the attached devices and going out to the outside.

It is a wonder that my rule set sort of works.

Kindest regards,

M
Reply With Quote
  #6   (View Single Post)  
Old 31st December 2024
jggimi's Avatar
jggimi jggimi is offline
More noise than signal
 
Join Date: May 2008
Location: USA
Posts: 8,099
Default

I interpret ":network" to mean "all the subnet addresses that can be reached via this NIC." If I have a NIC configured with the IPv4 address (and CIDR netmask) 198.51.100.20/24, then the IPv4 ":network" range would be that entire /24 subnet: the 256 addresses between 198.51.100.0 and 198.51.100.254 for devices, with .255 reserved for broadcast. Packets forwarded from other networks through to that NIC would be outside the :network range.

With PF, it helps to remember that "from" "to" "in" "out" and "on" just restrict what traffic will match the rule. A rule with "on" will only apply to traffic transiting the named NIC. The "in" and "out" options apply to traffic direction -- from the point of view of the system running PF. Rules that use ":network" will further restrict what traffic matches the rule, as it will only match traffic that originates from or terminates to devices with ":network" addresses, and won't match traffic forwarded to or from other networks, such as traffic flowing to and from the Internet.
Reply With Quote
  #7   (View Single Post)  
Old 1st January 2025
mefisto mefisto is offline
Shell Scout
 
Join Date: Sep 2017
Posts: 110
Default

Hi jggimi,

thank you for trying to help me understand, but the more I am working on the rules, the more I am convinced that it is just a pure luck that I am as far -by my admittedly low standards - as I am. As I am now struggling with routing between the LANs, by means of an example consider this rule:

Code:
pass in on $lan_1 from $lan_1:network to $lan_2:network
I interpret it as, packets incoming on the $lan_1 interface from any of the members of the $lan_1 network are to be delivered to any member of the $lan_2: network.

But, since the packet needs to go out, why not to write it as follows:

Code:
pass out from $lan_1:network to $lan_2:network
BTW, neither seems to work for me.

No wonder that I feel like taking a rope and go shoot myself into a lake.

Kindest regards,

M

BTW, have a healthy and prosperous New Year, both in your personal and professional life.

M
Reply With Quote
  #8   (View Single Post)  
Old 1st January 2025
jggimi's Avatar
jggimi jggimi is offline
More noise than signal
 
Join Date: May 2008
Location: USA
Posts: 8,099
Default

Let's look at both rules.
Quote:
pass in on $lan_1 from $lan_1:network to $lan_2:network
This is a pass rule. It will match traffic inbound (to the PF machine) arriving to the PF system on NIC $lan_1, only if the "from" address is a member of the IPv4 or IPv6 subnets, and the "to" address is a member of the subnets assigned to NIC $lan_2. If the rule matches, and it is the last matching rule, the traffic will be passed. If state is established by this inbound traffic, this rule will permit responding packets of the state to also pass.
Quote:
pass out from $lan_1:network to $lan_2:network
I think this rule will never match any traffic. In this rule, the "out" option will only match traffic exiting the PF system, while the "from" option will only match traffic entering the PF system. These two options are in conflict.

You can see which rules are applied to traffic with tcpdump(8) and pflog(4). The matching rule, pass or block, is reported by rule number. You can use pfctl(8) to translate the rule number to the rule with # pfctl -sr -R <number>.

I try to avoid using "in", "out", and "on" unless they're truly necessary, because it's easy to confuse them, and they limit what traffic will match.
Reply With Quote
  #9   (View Single Post)  
Old 1st January 2025
mefisto mefisto is offline
Shell Scout
 
Join Date: Sep 2017
Posts: 110
Smile

Hi jggimi,

your explanation
Quote:
It will match traffic inbound (to the PF machine) arriving to the PF system on NIC $lan_1
is likely correct. But how is one supposed to discern it from the following from pf.conf:
Code:
in or out
    A packet always comes in on, or goes out through, one interface. in and out apply to incoming and outgoing packets; if neither are specified, the rule will match packets in both directions.
Note that it does not say anything about "arriving to the PF system".

So, if "in and "out" refer to the PS system, then how to write a rule for routing between lan_1 and lan_2? Like this:
Code:
pass from $lan_1:network to $lan_2:network
or
Code:
pass on $vlan_1 from $lan_1:network to $lan_2:network
Nope, neither works. I give up, at least till next year.

Kindest regards.

M
Reply With Quote
Old 1st January 2025
jggimi's Avatar
jggimi jggimi is offline
More noise than signal
 
Join Date: May 2008
Location: USA
Posts: 8,099
Default

The "PF system" in my post above is a short form for "the operating system where PF is running."

When that operating system is acting as a network router, packets arrive at the system via one NIC, and are then forwarded for departure via a different NIC, usually. The "in" filter option limits the rule to arriving packets, while the "out" filter option limits rules to departing packets.

If instead of using "in" "out" and "on" your rules were written with only "from" and "to", packet direction and NIC selection no longer limit possible matches. For example, consider this simple rule set. There's no NICs mentioned, and no packet direction. But, I do need to have subnet level "network" addresses known when crafting these rules:
Quote:
block
pass from 203.0.113/24 to any
pass from 198.51.100/24 to 192.0.2/24
pass from 192.0.2/24 to 198.51.100/24
  1. The first rule is a default block. If a packet does not match any other rule, this rule will match and the packet will be blocked.
  2. The second rule is a pass rule, and will match any IP traffic of any kind from the 203.0.113/24 subnet, going to anywhere. Any of the 145 or more IP protocols, including the ones we're most familiar with: TCP, UDP, and ICMP. Some of those protocols, such as TCP, create state, so returning traffic will pass. Some traffic might not create state, and returning traffic would be blocked, as it would only match the default block rule.
  3. The third rule passes all traffic from 198.51.100/24 to 192.0.2/24, but if state is not created, returning traffic would be blocked. So...
  4. The very last rule is a pass in the opposite direction, ensuring that two-way traffic between these two subnets is permitted regardless of which subnet initiates the traffic, and whether state has been maintained.
Reply With Quote
Old 1st January 2025
mefisto mefisto is offline
Shell Scout
 
Join Date: Sep 2017
Posts: 110
Default

Hi jggimi,

thank you for your patience, it is now very clear to me what you meant by the limitation adding all the options, as well as the OS on which the PF is running.

Without any disrespect meant, I do understand the keep state and/or matching rules. Hence I have them in my configuration:
Code:
#---------------------------------#
# VLAN 192.168.1.0/24
#---------------------------------#

# Allow traffic to any member of VLAN to any other member and the Internet 
pass in on $vlan_1

# Block DNS queries not addressed to internal DNS server.
block return in quick on $vlan_1 proto { udp tcp } to ! $vlan_1 port { 53 853 }

# Allow connection to $vlan_2
pass from $vlan_1:network to $vlan_2:network

# Allow data packets to pass from the router out through the NIC to the
# computers or devices attached.
pass out on $vlan_1 inet keep state

# NAT
pass out on $ext_if inet from $vlan_1:network to any nat-to ($ext_if)

#---------------------------------#
# VLAN 192.168.2.0/24
#---------------------------------#

# Allow traffic to any member of VLAN to any other member and the Internet 
pass in on $vlan_2

# Block DNS queries not addressed to internal DNS server.
block return in quick on $vlan_2 proto { udp tcp } to ! $vlan_2 port { 53 853 }

# Allow connection to $vlan_1
pass from $vlan_2:network to $vlan_1:network

# Allow data packets to pass from the router out through the NIC to the
# computers or devices attached.
pass out on $vlan_2 inet keep state

# NAT
pass out on $ext_if inet from $vlan_2:network to any nat-to ($ext_if)
Please see the matching rules in vlan_1 and vlan_2 configuration.

Kindest regards,

M
Reply With Quote
Old 2nd January 2025
jggimi's Avatar
jggimi jggimi is offline
More noise than signal
 
Join Date: May 2008
Location: USA
Posts: 8,099
Default

At least that excerpt has rules and comments that are easy for me to read and to understand your intent.

I went back through the PF User's Guide and found this reference to the various modifiers, located in the NAT section. It may be clearer than what's in pf.conf(5):
Quote:
The name or group of a network interface followed by any one of these modifiers:

:network - substitutes the CIDR network block (e.g., 192.168.0.0/24)
:broadcast - substitutes the network broadcast address (e.g., 192.168.0.255)
eer - substitutes the peer's IP address on a point-to-point link

In addition, the :0 modifier can be appended to either an interface name/group or to any of the above modifiers to indicate that PF should not include aliased IP addresses in the substitution. These modifiers can also be used when the interface is contained in parentheses. Example: fxp0:network:0
Reply With Quote
Old 2nd January 2025
mefisto mefisto is offline
Shell Scout
 
Join Date: Sep 2017
Posts: 110
Default

Hi jggimi,

well, I always make copious notes to (i) clarify in my mind what I am trying to do and (ii) to remember what I did.

I also looked at the documentation, as as I am interpreting it, a matching pass rule automatically creates keep state. Regardless, keep state or my two rules, I still cannot route.

I spent another frustrating time on that, nothing that I tried or saw in other people's configuration seems to work for me. I have even learned about tcdump, but I do not quite understand its usefulness. For example, if I see that ping is not getting a response, what good is it to see the same information on tcdump?

Kindest regards,

M
Reply With Quote
Old 2nd January 2025
jggimi's Avatar
jggimi jggimi is offline
More noise than signal
 
Join Date: May 2008
Location: USA
Posts: 8,099
Default

Quote:
Originally Posted by mefisto View Post
I still cannot route.
Is the syctl `net.inet.ip.forwarding` truly set to 1? If it is, then I recommend starting with a very simple temporary configuration, perhaps default pass with nat-to, just to confirm the problem is in your pf.conf file.
Quote:
...if I see that ping is not getting a response, what good is it to see the same information on tcdump?
If logging is enabled for all rules, you can see exactly which rule is matching each packet. Rather than adding a "log" option to every rule, I just add these two lines at the end of every pf.conf(5) file I manage:
Code:
# enable for logging:
#match log (matches)
I un-comment when I want to use pflog. Then, # tcpdump -nei pflog0 I'll see every matching pass or block, with rule number. Rule numbers can be converted to the filter rule text with # pfctl -sr -R <number>.
Reply With Quote
Old 2nd January 2025
mefisto mefisto is offline
Shell Scout
 
Join Date: Sep 2017
Posts: 110
Default

Hi jggimi,

thank you for your continued help.

Quote:
Originally Posted by jggimi View Post
Is the syctl `net.inet.ip.forwarding` truly set to 1? If it is, then I recommend starting with a very simple temporary configuration, perhaps default pass with nat-to, just to confirm the problem is in your pf.conf file.
Yes, it is enabled. First, I checked the correct file about 7,876,040 times, second, I can see the state change during boot.

Tha nat-to is working, I can access the Internet from both VLANs. So, my lizard brain reasons that the routing is (partially) working. (They are not actual VLANs yet, I have the testing computers on different switches).

I can ping every device on the VLANs network from the firewall, but not from any of the VLANs, which seems consistent with the inter-LAN routing failure..

Quote:
Originally Posted by jggimi View Post
If logging is enabled for all rules, you can see exactly which rule is matching each packet. Rather than adding a "log" option to every rule, I just add these two lines at the end of every pf.conf(5) file I manage:
Code:
# enable for logging:
#match log (matches)
I un-comment when I want to use pflog. Then, # tcpdump -nei pflog0 I'll see every matching pass or block, with rule number. Rule numbers can be converted to the filter rule text with # pfctl -sr -R <number>.
Thank you for describing the commands. Is there a way to isolate a specific traffic, i.e., from a specific machine to specific interfaces? But, returning to my last post, how will I know, which rule is wrong, either transmitting the packet or blocking it.

I do not know, how else to approach it, as I had been working on the inter-LAN routing for past three days, trying -out of desperation - every rule that people posted, (even yours or J65nko's, who also seems knowledgeable), but nothing seems to work.

Kindest regards,

M
Reply With Quote
Old 2nd January 2025
jggimi's Avatar
jggimi jggimi is offline
More noise than signal
 
Join Date: May 2008
Location: USA
Posts: 8,099
Default

You can limit the tcpdump output to traffic to or from a specific host.
Code:
# tcpdump -nei pflog0 host 192.168.9.9
You can also limit the tcpdump output to traffic that has a specific direction, with source or destination.
Code:
# tcpdump -nei pflog0 src host 192.168.9.9
And you can limit the tcpdump output to traffic between two hosts.
Code:
# tcpdump -nei pflog0 src host 192.0.2.5 and dst host 198.51.100.27
For lots more confusing ways to have tcpdump limit its output, see the tcpdump(8) man page.
Reply With Quote
Old 2nd January 2025
mefisto mefisto is offline
Shell Scout
 
Join Date: Sep 2017
Posts: 110
Default

Hi jggimi,

thank you very much for the tcpdump commands, I will see if I can find the problem. If not, I plan to comment all the specific blocking rules, e.g., RFC1918, no-route, urpf-failed, etc., with just
Code:
block all
and if that helps, I will start nu-commenting them one at a time.

If it does not help, well, it will be an indication that I am too stupid for setting the firewall/router.

Kingest regards,

M
Reply With Quote
Old 2nd January 2025
jggimi's Avatar
jggimi jggimi is offline
More noise than signal
 
Join Date: May 2008
Location: USA
Posts: 8,099
Default

If the traffic you expect to be matched by a pass rule gets blocked instead, you'll be able to see it. Then, determining WHY that specific rule doesn't match becomes the problem.
Reply With Quote
Old 2nd January 2025
mefisto mefisto is offline
Shell Scout
 
Join Date: Sep 2017
Posts: 110
Default

Hi jggimi,

Quote:
If the traffic you expect to be matched by a pass rule gets blocked instead, you'll be able to see it. Then, determining WHY that specific rule doesn't match becomes the problem.
O.K., but that is the problem with the tcpdump that I noted previously. I do not need tcpdump to verify that the traffic is not passing between the LANs, I already know that. So, what is the purpose it the tcpdump.? Or, can I perhaps write a tcpdump query that will show me that the traffic passed LAN_1 interface but not passed or even arrived at Lan_2 interface? That would definitely be helpful. I will have to look at the tcpdump(8).

If not, would it not be more efficient to forget about the tcpdump and proceed with the proposed elimination and re-insertion the blocking rules?

Kindest regards,

M
Reply With Quote
Old 2nd January 2025
jggimi's Avatar
jggimi jggimi is offline
More noise than signal
 
Join Date: May 2008
Location: USA
Posts: 8,099
Default

If you can, please show me some of the tcpdump output, including the rule that blocked, and the pass rule you expected to have pass, but which didn't match.

(You haven't posted the complete pf.conf, so I'm unsure if you've got an early "block quick" which accidentally interferes with the traffic you want to have pass in later rules.)
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
OpenBSD firewall/router with (so far) two minor issues mefisto OpenBSD Security 3 29th December 2024 03:03 AM
Hardware for embedded FreeBSD/OpenBSD custom router/firewall ( Ent. firewall, ADSL ro Bsaidus General Hardware 5 24th November 2023 09:57 PM
Smallest, cheapest hardware for OpenBSD router + firewall beiroot OpenBSD General 22 12th April 2018 09:37 AM
MacVTap VEPA with OpenBSD router/firewall, need bridge to reflect on same segment rbigm101 OpenBSD Security 17 20th September 2016 04:03 PM
OpenBSD amd64 or i386 for firewall/router J65nko OpenBSD General 7 24th December 2009 09:06 PM


All times are GMT. The time now is 05:54 PM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Content copyright © 2007-2010, the authors
Daemon image copyright ©1988, Marshall Kirk McKusick