lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <1390360937.26514.24.camel@ceramic.home.fifi.org>
Date:	Tue, 21 Jan 2014 19:22:17 -0800
From:	Philippe Troin <phil@...i.org>
To:	"netdev@...r.kernel.org" <netdev@...r.kernel.org>
Subject: Weirdness with combined SNAT/DNAT, bridging and promiscuous mode

I ran into a weird bridging issue that I wanted to share with this list.
This was found on Fedora 19 running with the latest 3.12.8.200.fc19
x86_64 kernel.

I have the following network (simplified):

  +-----+
  | ex1 |
  +-----+
     | 10.0.0.2/24
     |
     | 10.0.0.1/24
  +--------+
  | router |
  +--------+
     | 192.168.1.1/24
     |
     | 192.168.1.2/24
  +-----+
  | in1 |
  +-----+

Ex1 is on the exterior (internet), in1 on the interior sides.
I want to forward a port from 10.0.0.1:2222 to 192.168.1.2:22.
I use an iptables DNAT target on the router's nat PREROUTING chain, all
is fine, when I connect from ex1 to 10.0.0.1:2222, it works.

If I want to forward connections from router's 10.0.0.1:2222 to in's
192.168.1.2:22, I add the same rule DNAT to the OUTPUT chain.

If now I also want to allow connections from in1 to 10.0.0.1:2222 to be
looped back to in1's port 22, it's also possible by adding an extra SNAT
rule.

At this point, I have the following network scripts:

      * ex1
                ip link set up dev eth0
                ip addr add 10.0.0.2/24 dev eth0
                
      * router
                ip link set up dev eth0
                ip addr add 10.0.0.1/24 dev eth0
                ip link set up dev eth1
                ip addr add 192.168.1.1/24 dev eth1
                iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 10.0.0.1
                iptables -t nat -A OUTPUT -p tcp -d 10.0.0.1 --dport 2222 -j DNAT --to 192.168.1.2:22
                iptables -t nat -A PREROUTING -p tcp -d 10.0.0.1 --dport 2222 -j DNAT --to 192.168.1.2:22
                iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 192.168.1.2 -p tcp --dport 22 -j SNAT --to-source 192.168.1.1
                sysctl net.ipv4.ip_forward=1
                
                
      * in1
                ip link set up dev eth0
                ip addr add 192.168.1.2/24 dev eth0
                ip route add 0.0.0.0/0 via 192.168.1.1

>From all three machines, connecting to 10.0.0.1:22 will forward the TCP
connection to 192.168.1.2:22.

Now, let's introduce a bridge. If make eth1 join a bridge br1, the
script for the router machine becomes:

        brctl addbr br1
        brctl addif br1 eth1
        
        ip link set up dev eth0
        ip addr add 10.0.0.1/24 dev eth0
        
        ip link set up dev eth1
        ip link set up dev br1
        ip addr add 192.168.1.1/24 dev br1
        
        iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 10.0.0.1
        iptables -t nat -A OUTPUT -p tcp -d 10.0.0.1 --dport 2222 -j DNAT --to 192.168.1.2:22
        iptables -t nat -A PREROUTING -p tcp -d 10.0.0.1 --dport 2222 -j DNAT --to 192.168.1.2:22
        iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 192.168.1.2 -p tcp --dport 22 -j SNAT --to-source 192.168.1.1
        sysctl net.ipv4.ip_forward=1

And now, although I can connect to 10.0.0.1:22 fine from ex1 and router,
but connecting from in1 fails.
The connection hangs.
Tcpdump (without turning promiscuous mode on) shows that the syn packets
from in1 show up on router's eth1 interface, but are not visible to the
br1 bridge.  The MAC addresses on the frames seem to correct (both br1
and eth1 have the same MAC in this set-up, by default).

Oddly enough, turning on promiscuous mode on br1 makes everything work.
Changing promiscuous mode on eth1 has no effect.

Why would the promiscuous mode on the bridge itself change the behavior
of the iptables script above?

I could understand promiscuous mode and physical interface's MAC
filters, but I thought that promiscuous mode on a bridge interface was a
no-op.

A quick grep shows that IFF_PROMISC is used in the bridging code in
br_pass_frame_up() and br_handle_frame_finish(), both in br_input.c.

Am I supposed to turn on promiscuous mode on bridge interfaces, or is it
something else (bug in my iptables script, bug in bridging)?

Thanks for reading this long-winded email.
Phil.


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ