ipfw with nat - allowing by MAC address
Patrick Tracanelli
eksffa at freebsdbrasil.com.br
Mon Apr 23 00:31:34 UTC 2007
I could not understand Joao's statement, so I tend to disagree that
there is no layer2 traffic flowing on a NAT box. Makes no sense to me. I
am sure it is possible to do all 2 sub-layer layer 2 filtering (MAC and
LLC).
So I have just tried what you are willing to get working Lubomir, right
now in the network I am.
My current enviroment is the simplest the possible:
[ 10.69.0.0/16 network ] <=> [ switch ] <=> [FreeBSD] <=> [Internet]
My external interface is vr0
My internal one is xl0
I have just allowed two stations to go to the DIVERT (natd) rules by
using skipto approach, and all other machines are not skipped, so they
tend to match an intermediary rule which does deny all traffic based on
layer2. I kept only the relevant rules so it gets very clear to understand:
# ipfw show
00300 688 62538 skipto 1000 ip from any to any { MAC any
08:00:46:bd:da:a3 or MAC any 00:17:31:df:bc:ab } layer2
00310 637 84252 skipto 1000 ip from any to any { MAC
08:00:46:bd:da:a3 any or MAC 00:17:31:df:bc:ab any } layer2
00500 468 30071 deny log logamount 100 ip from any to any MAC any
any layer2 via xl0
01000 527 50710 divert 8668 ip from 10.69.0.0/16 to any out via vr0
01100 556 68585 divert 8668 ip from any to me in via vr0
65535 14642 1214437 allow ip from any to any
In case ipfw list may be clearer:
# ipfw list
00300 skipto 1000 ip from any to any { MAC any 08:00:46:bd:da:a3 or MAC
any 00:17:31:df:bc:ab } layer2
00310 skipto 1000 ip from any to any { MAC 08:00:46:bd:da:a3 any or MAC
00:17:31:df:bc:ab any } layer2
00500 deny log logamount 100 ip from any to any MAC any any layer2 via xl0
01000 divert 8668 ip from 10.69.0.0/16 to any out via vr0
01100 divert 8668 ip from any to me in via vr0
65535 allow ip from any to any
Some relevant information: I am doing selective divert based on my
network, on vr0 (external interface) while explicitly denying all layer2
traffic based on mac, on rule 500, only on xl0 (internal network),
because if I do it on all networks or on vr0, I will certainy deny my
own outgoing packets.
So it worked perfectly, and right now while I send this message only the
two MAC addresses are allowed to get diverted to natd (and go to internet).
As you can see, some traficc is still hitting rule # 500, so I want to
know what it is:
# grep 500 /var/log/security | tail -5
Apr 22 19:54:32 HomerSimpson kernel: ipfw: 500 Deny UDP
208.239.76.163:5060 10.69.69.39:5060 out via xl0
Apr 22 19:54:33 HomerSimpson kernel: ipfw: 500 Deny MAC in via xl0
Apr 22 19:54:36 HomerSimpson kernel: ipfw: 500 Deny UDP
208.239.76.163:5060 10.69.69.39:5060 out via xl0
Apr 22 19:54:37 HomerSimpson kernel: ipfw: 500 Deny MAC in via xl0
Apr 22 19:54:50 HomerSimpson kernel: ipfw: limit 100 reached on entry 500
So, it is IP 10.69.69.39, which for sure has a different MAC address:
# arp 10.69.69.39
? (10.69.69.39) at 00:12:17:fb:ee:e7 on xl0 [ethernet]
You also said you wanted allow other stations to talk to the gateway,
what in the above examples, I am not allowing, so for example if I add
rule 400 like this:
# ipfw add 400 allow all from 10.69.0.0/16 to me via xl0 not layer2
keep-state
00400 allow ip from 10.69.0.0/16 to me via xl0 not layer2 keep-state
I am certainly allowing any station on 10.69/16 network, regardless of
its IP address (unless it is on 10.69/16 network) or MAC address (since
I am not filtering on layer2):
# ipfw show
00300 2544 519800 skipto 1000 ip from any to any { MAC any
08:00:46:bd:da:a3 or MAC any 00:17:31:df:bc:ab } layer2
00310 2415 601710 skipto 1000 ip from any to any { MAC
08:00:46:bd:da:a3 any or MAC 00:17:31:df:bc:ab any } layer2
00400 29 2548 allow ip from 10.69.0.0/16 to me via xl0 not layer2
keep-state
00500 1236 65813 deny log logamount 100 ip from any to any MAC any
any layer2 via xl0
01000 1904 469946 divert 8668 ip from 10.69.0.0/16 to any out via vr0
01100 2049 525859 divert 8668 ip from any to me in via vr0
65535 42049 5911000 allow ip from any to any
Since ipfw is a first-match-based firewall you don't need to worry about
this "allow from any to any" rule, because the hosts which get to this
rule certainly were not skipped on the later rules, so they simply never
get diverted, because they match on this "allow" and divert rules
happens AFTER the allow.
Lets see who is matching rule # 400 (which is a keep-state rule, so it
is generating dynamic state rules):
## Dynamic rules (2):
00400 1 100 (1s) STATE tcp 10.69.2.40 59235 <-> 10.69.2.1 22
00400 0 0 (0s) STATE udp 10.69.69.13 59577 <-> 10.69.69.1 53
Both 10.69.2.1 and 10.69.69.1 are "me" (the firewall itself). So just
perfect, anyone can freely go through the private network, in the above
dynamic we see an ssh session and an expired DNS query to the firewall
which for sure is also the DNS server for the network).
Last thing, remember to enabled ethernet filtering on IPFW:
sysctl -w net.link.ether.ipfw=1
If not, no layer2 filtering will be processed at all.
Also, when doing layer2 filtering, remember that the default IPFW
behavior is to filter layer3 and above layers, but when you set
net.link.ether.ipfw to true, it does layer2 and above, so all traffic
going via ether_demux() and ether_output_frame() gets filtered.
But the thing is that on the IP stack - /sys/net/if_ethersubr.c (where
ether_demux() and ether_output_frame() happen) - layer2 traffic happen
before the upper layers. So when doing ipfw layer firewall remember:
- layer2 rules will get processed first
- non layer specified rules will get processed two times, on layer2 and
upper layers
- not layer2 (meaning all upper layers) will get processed only later
Hope this working example is a good start poing for your setup.
Lubomir Georgiev escreveu:
> Thanks for the response but I have to disagree with you - I have read the
> responses time and time again with great attention, but to no avail. From
> what you said I understand that in order to utilize MAC address filtering I
> would need a managed switch or another box aside from the one that will be
> performing the NATing - is that right? Are you sure that there's no way to
> combine MAC filtering with NAT in a single box?
>
> Just to make things clear I'll give an example of what I want to do - I
> want a machine with say MAC-a to have internet connectivity regardless of
> its IP address - that is I can assign to it any of the
> 192.168.1.Xaddresses. But if a machine with say MAC-b comes into the
> network and tries
> any IP I want it to be excluded from the NATd rule but still have
> connectivity with the FreeBSD box - so that I can open up a terminal and
> add
> it to the rulelist if I want Inet connectivity on that machine.
>
>
>
> P.S. I have heard of another way of filtering which uses the ARP tables -
> any comments on that? The thing that I don't think I'll be able to
> accomplish with the ARP tables is to use any of the 192.168.1.X IP
> addresses.
>
> Once again thanks for all your help and I hope we can reach the final
> conclusion of this problem.
>
--
Patrick Tracanelli
FreeBSD Brasil LTDA.
(31) 3281-9633 / 3281-3547
316601 at sip.freebsdbrasil.com.br
http://www.freebsdbrasil.com.br
"Long live Hanin Elias, Kim Deal!"
More information about the freebsd-ipfw
mailing list