Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

#175 NAT rule needs "-o <interface>" stripped

open
Vadim Kurland
None
5
2011-10-15
2011-06-16
Michael Monnerie
No

I created a NAT rules which says
original src: 10.127.125.3
translated src: 10.127.127.1
and that generated this rule:
echo "-A POSTROUTING -o eth1 -s 10.127.125.3 -j SNAT --to-source 10.127.127.1 "

But that is wrong, I need it without "-o eth1":
iptables -t nat -I POSTROUTING -s 10.127.125.3 -j SNAT --to-source 10.127.127.1

That is because LAN 10.127.125.x is on another interface than 10.127.127.x. It works with my manual rule applied, but doesn't with the one from fwbuilder. How can I convince fwbuilder to strip the "-o eth1" from the rule?

Discussion

1 2 > >> (Page 1 of 2)
  • Mike Horn
    Mike Horn
    2011-06-16

    What version of fwbuilder are you running? Also, what are the interfaces and IP addresses that are configured on your firewall?

     
  • # fwbuilder -version
    4.1.3

    # ifconfig (stripped)
    eth0 Link encap:Ethernet Hardware Adresse DA:63:44:A2:EF:B7
    inet Adresse:195.x.y.z

    eth0:0 Link encap:Ethernet Hardware Adresse DA:63:44:A2:EF:B7
    inet Adresse:10.127.125.1 Bcast:10.127.125.255 Maske:255.255.255.0

    eth1 Link encap:Ethernet Hardware Adresse 06:72:E4:74:DF:D8
    inet Adresse:10.127.127.1 Bcast:10.127.127.255 Maske:255.255.255.0

    eth1:2 Link encap:Ethernet Hardware Adresse 06:72:E4:74:DF:D8
    inet Adresse:10.127.126.1 Bcast:10.127.126.255 Maske:255.255.255.0
    UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

    The rule generates "-o eth1", but it comes in at eth0. As this is a POSTROUTING rule, and the rule itself changes the source IP in a way that it must go out on eth1 instead eth0, I wonder if the kernel then does the PRE/POSTROUTING rules again?

     
  • Mike Horn
    Mike Horn
    2011-06-17

    The -o refers to the outbound interface which in your cases looks like it should be eth1 (-i refers to inbound interface). Do you see anything in the /var/log/messages file when you have the fwbuilder generated NAT rule installed?

    Also, you can upgrade to Firewall Builder v4.2 which allows you to explicitly define the inbound and outbound interfaces on your NAT rules. I don't think this is going to directly solve your problem, but it will give you more flexibility in defining your NAT rules.

     
  • I've checked now, the fwbuilder x64 repo on your site is from December and has
    fwbuilder-4.1.3-b3421.suse11.2.x86_64.rpm
    in it. Could someone please upgrade that, so I can get 4.2?

     
  • And on your download page under "Third Party Packages" the last two links offer fwbuider 3.0. The first offers 4.2.2, but I can't find libfwbuilder, just fwbuilder is there. A cleanup would be good for that links.

     
  • Mike Horn
    Mike Horn
    2011-06-17

    Starting in v4.2 there is no separate libfwbuilder package to install, everything is included in the fwbuilder package. Release notes for v4.2 are here:

    http://www.fwbuilder.org/4.0/docs/firewall_builder_release_notes.html#4.2.0

    Thanks for pointing out the links with older packages. These sites and packages are maintained by volunteers on their own, so I'll add a note that these may be out of date.

     
  • Mike Horn
    Mike Horn
    2011-06-17

    Did you see my comments about outbound vs. inbound interface? I don't think v4.2 will solve your issue, since creating the rule with "-o eth1" appears to be correct based on your configuration.

     
  • Vadim Kurland
    Vadim Kurland
    2011-06-20

    looks like repository hasnt been updated, perhaps build failed on OpenSUSE build machines but I did not notice. However the source rpm is available for download in the "Files" section here on SF, you could build from that.

     
  • OK, I'm now on 4.2.2 but it didn't help. The problem is, you can't specify -i in POSTROUTING rules, and the auto-generated "-o eth1" doesn't work. I tried to modify it to "-o eth0", also fails. If I just delete the "-o eth1" all goes well. But there is currently no way to do that in fwbuilder, so this bug should be fixed please. Maybe an option to the single rule? Or just skip the default of specifying "-o" at all, as with 4.2 you can specify that if you want anyway. Why has it been specified at all? I'ts not neccessary anyway.

     
  • Vadim Kurland
    Vadim Kurland
    2011-06-20

    Could you explain what happens when you apply rule with "-o eth1" ? IP address 10.127.127.1 belongs to eth1 and as long as packets get routed out through eth1, the "-o eth1" clause should not break things since "-o" matches outbound interface. You say iptables does not allow "-i" in POSTROUTING chain, but fwbuilder does not generate "-i" clause, it generates "-o". HAving "-o" in the rule says nothing about inbound interface an the rule should match packets coming into the firewall through any interface, just like the rule without "-i" and "-o" clause.

    Please explain what do you mean when you say it does not work.

     
  • Just this can be seen on the firewall:
    09:10:01.406026 IP 10.127.125.3.7206 > 10.127.128.5.25: Flags [S], seq 1497501, win 1446, options [mss 1446], length 0
    09:10:01.406136 IP 10.127.125.3.7206 > 10.127.128.5.25: Flags [S], seq 1497501, win 1446, options [mss 1446], length 0
    09:16:52.440851 IP 10.127.125.3.7207 > 10.127.128.5.25: Flags [S], seq 15558242, win 1446, options [mss 1446], length 0
    09:16:52.440927 IP 10.127.125.3.7207 > 10.127.128.5.25: Flags [S], seq 15558242, win 1446, options [mss 1446], length 0

    A "SYN" is tried but doesn't work. If I take away the "-o eth" part, it works:
    09:17:22.517076 IP 10.127.125.3.7208 > 10.127.128.5.25: Flags [S], seq 11268006, win 1446, options [mss 1446], length 0
    09:17:22.517142 IP 10.127.127.1.7208 > 10.127.128.5.25: Flags [S], seq 11268006, win 1446, options [mss 1446], length 0
    09:17:22.521874 IP 10.127.128.5.25 > 10.127.127.1.7208: Flags [S.], seq 892694522, ack 11268007, win 5840, options [mss 1368], length 0
    09:17:22.526024 IP 10.127.128.5.25 > 10.127.125.3.7208: Flags [S.], seq 892694522, ack 11268007, win 5840, options [mss 1368], length 0
    09:17:22.526175 IP 10.127.125.3.7208 > 10.127.128.5.25: Flags [.], ack 1, win 1446, length 0
    09:17:22.526186 IP 10.127.127.1.7208 > 10.127.128.5.25: Flags [.], ack 1, win 1446, length 0

    I guess what happens is this:
    Packet arrives @eth0, from ip 10.127.125.3 (raid controller) to 10.127.128.5 (mailserver)
    NAT has this rule:
    echo "-A POSTROUTING -o eth0 -s 10.127.125.3 -j SNAT --to-source 10.127.127.1 "
    And this rule hits, so source is changed to 10.127.127.1, but that IP subnet is located on eth1. So the packet (just guessing here!) is again put into the network queue, and now it should go out on eth1. But then above rule doesn't hit. In this weird situation it looks like the packet is just dropped. At least I can't see any sign of it anymore, it doesn't arrive on the destination and I see nothing go back to the origin IP (like TCP RST or so).

    Just taking out the "-o eth0" part makes everything work. I wonder why "-o eth0" was specified automatically by fwbuilder. The kernel does the right thing if you don't specify it, and I'd only use it if the user specified it - especially now that fwbuilder 4.2 allows to specify it.

    Sorry that I puzzled you with my "-i eth" words. What I meant is the rule could work if "-i eth0" was specified, except that iptables doesn't support that. So it can't be used anyway.

     
  • Vadim Kurland
    Vadim Kurland
    2011-06-20

    You say:

    -----------------------------------------------------------
    I guess what happens is this:
    Packet arrives @eth0, from ip 10.127.125.3 (raid controller) to
    10.127.128.5 (mailserver)
    NAT has this rule:
    echo "-A POSTROUTING -o eth0 -s 10.127.125.3 -j SNAT --to-source 10.127.127.1 "
    -----------------------------------------------------------

    original report quoted this rule with "-o eth1", not eth0. Which one it is ?

    Which interface did you run tcpdump captures on ? Was it eth0 or eth1 ? You can use this command to capture packets on eth1:

    tcpdump -n -i eth1 host 10.127.128.5

    Also, could you show the output of the command

    ip route list match 10.127.128.5

    The "-o eth1" is matching clause, if the rule does not match the packet when this clause is present, then the packet must be routed through another interface. In other words, having "-o eth1" can not break the rule unless it does not match routing configuration.

     
  • Oh sorry. I still had the "interface out" set to "eth0" now. I removed it, to let it on "auto", and then fwbuilder generates it with "-o eth1". So fwbuilder recognizes on which interface the resulting packet should go out.

    This is what puzzled me first: We are in POSTROUTING, change the source, and now the packet should go out on another interface. Is the packet directly pushed out there, or is it again moved through PRE/POSTROUTING rules on that interface?

    My tcpdump on that host was:
    tcpdump -niany '(host 10.127.125.3 or host 10.127.127.1) and port 25'
    And I also listened on the target host (10.127.128.5):
    tcpdump -niany '(host backup2 or net 10.127.125.0/24 or host backup1 or net 10.127.128.0/24 or net 10.127.127.0/24) and port 25'
    But nothing ever arrives there.

    # ip route list match 10.127.128.5
    10.127.128.0/24 via 10.100.255.7 dev tun0
    default
    nexthop via 195.202.151.129 dev eth0 weight 1
    nexthop via 195.202.170.129 dev eth2 weight 1
    That's all right. 10.127.128.x goes through the tunnel, and the tunnel works:
    # ping 10.127.128.5
    PING 10.127.128.5 (10.127.128.5) 56(84) bytes of data.
    64 bytes from 10.127.128.5: icmp_seq=1 ttl=63 time=4.69 ms
    backup1:~ # telnet 10.127.128.5 25
    Trying 10.127.128.5...
    Connected to 10.127.128.5.
    Escape character is '^]'.
    220 mailsrv.XXXX ESMTP XXXX

    To some degree I solved it thanks to your question. I've had to set the "out interface" to tun0, then it works.
    Still, the automatic generated rule doesn't work, and up to fwbuilder 4.1 is not fixable. Also, looking just at the fwbuilder graphical rules there's no error, you can only see it by looking at the generated rules. The best would have been to just not insert "-o" by default, because then it also works.

     
  • Vadim Kurland
    Vadim Kurland
    2011-06-21

    You say :
    -----------------------------------------------------------------------------------
    This is what puzzled me first: We are in POSTROUTING, change the source,
    and now the packet should go out on another interface.

    -----------------------------------------------------------------------------------

    why changing source address of a packet makes it go out through another interface ? Routing decision is based on the destination address which does not change in this setup.

    the "ip route list" command shows that packet is actually routed out through the tunnel interface tun0 rather than eth1. This explains why iptables command that matches outbound interface "-o eth1" does not match the packet.

    You can simply put interface object tun0 in the outbound interface column in the nat rule to make generated iptables command match it with "-o tun0"

     
  • Alright, using "out interface"=tun0 works. But why does fwbuilder generate the "-o" rule by default anyway? If it would skip that, the rule would also work, and I'd have no manual specifying need. So currently, the auto-generated "-o" insertion leads to a non-working rule, and that should be fixed please.

     
  • Vadim Kurland
    Vadim Kurland
    2011-06-22

    we'll consider removing automatically generated "-o" match. It actually makes sense now that the user can add interface objects to the rule to explicitly add "-i" and "-o" matches.

     
  • I'm reposting here because I had the same issue again:
    auto-generated rule says this:
    echo "-A POSTROUTING -o vlan27 -s 172.17.0.2 -d 10.127.0.0/16 -j SNAT --to-source 10.72.27.1 "
    and I have to paste the "tun1" interface to "Interface out" to have it correct:
    echo "-A POSTROUTING -o tun1 -s 172.17.0.2 -d 10.127.0.0/16 -j SNAT --to-source 10.72.27.1 "

    The auto generated rule assumes that destination 10.127/16 is on vlan27 (is the decision done like this?), while it must pass over tun1 (openVPN). I understand the program cannot correctly know which interface to take, but why doesn't fwbuilder just leave the "-o <interface>" part away and generate the rule like this:
    echo "-A POSTROUTING -s 172.17.0.2 -d 10.127.0.0/16 -j SNAT --to-source 10.72.27.1 "
    That way, the kernel would be able to decide itself where to check it.

    Your last posting of 22.6.2011 says you consider this. Did you forget about it, or are there other implications when the "-o" is not generated?

     
  • Vadim Kurland
    Vadim Kurland
    2011-10-15

    fwbuilder has ability to guess the interface for the "-i" and "-o" clause of the generated iptables command, which works correctly in most of the cases and is useful feature. What it needs is a way for the user to express three possible states for the "Interface" column: "Auto" (let the program guess)", "All" (do not generate -i or -o at all) and "eth0" (user puts specific interface there manually). We do not have this ability right now and it is not going to be easy to add it because it requires changes in the internal data model and everything else.

    Another, even better way, to deal with the problem is to make fwbuilder policy compiler aware of the routing so that it can correctly guess that outbound interface in the example you provided is tun1 and not vlan27.

    This is what I mean by we will consider it. Unfrotunately this is not high on our priority list right now and I've been busy with other things. I'll keep this ticket open though, we'll get to it eventually.

     
  • Vadim Kurland
    Vadim Kurland
    2011-10-15

    • assigned_to: nobody --> vkurland
     
  • Vadim Kurland
    Vadim Kurland
    2011-10-15

    btw, you can try another workaround:

    I suppose address 10.72.27.1 belongs to one of the interfaces of the firewall. Is this so ? If yes, it is probably vlan27. You can create another standalone Address object with the same ip address and use it in the rule instead. This should turn the guessing algorithm off.

     
  • Thank you for the workaround. But it's actually easier to just insert the correct "out" interface than to create another object. This is error-prone, as changes to the original object would require a change to the "clone", and therefore it's not maintainable.

    When you say "is a useful feature" - why? What makes the rule with "-o" better than without? Performance of in-kernel rule interpretation? I can't see another benefit.
    To me, having a "bug" less is more worth than higher rule performance.

    And the problem why I'm crying here is that finding the problem is very hard, as the rule I generated are correct but it doesn't work. And as errors are so seldom in fwbuilder, I search everywhere else and that costs time...

    And your "better way" wouldn't work here, as there's a mix of routes defined:
    # route -n|grep 127
    10.127.5.0 10.100.255.4 255.255.255.0 UG 0 0 0 tun1
    10.127.4.0 10.100.255.4 255.255.255.0 UG 0 0 0 tun1
    10.127.124.0 0.0.0.0 255.255.255.0 U 0 0 0 vlan28
    10.127.125.0 0.0.0.0 255.255.255.0 U 0 0 0 vlan27
    10.127.28.0 10.100.255.4 255.255.255.0 UG 0 0 0 tun1
    This comes because 124+125 are currently in-house in test. So no correct route is defined, and fwbuilder will never be able to fix that automatically. The only solution is not to generate "-o" in our case.

     
  • Vadim Kurland
    Vadim Kurland
    2011-10-15

    It is not correct to always generate nat rules without "-o" clause. Here is an example when this breaks things:

    Suppose you have a firewall with two "outside" interfaces with different addresses and want to translate to a different address depending on the egress interface of a packet. You need two nat rules to translate to these two different outside addresses. The routing inside the kernel decides which interface the packet should be sent out through, but if our two NAT rules do not match interface using "-o" clause, then the firewall will always translate using the first rule of the two.

     
  • I understand. But in this case, I know that I have two interfaces and that I should create 2 NAT rules, and I should specify which interface I mean. If I don't specify interfaces and it doesn't work, I'll quickly solve it.

    In cases like mine, where I generate a correct-looking rule but fwbuilder deliberately decides to specify an interface (which I didn't), it's very hard to find the problem. The rule is semantically correct, just the generated rule is wrong. I guess there are many people who have less experience than me and just give up here.

    So while the special two-interface case is clear and easy to solve, my case just generates a rule different from what I meant, and therefore breaks behind of what is visible, and you have to check the ruleset to find the problem. I'd say that's a strong argument :-)

    At least if you auto-generate the -o interface, could you possibly insert it into the gui so that it's easy to see there's something wrong? I wouldn't like that, but better this than display nothing and generate a rule different from what I want and see.

    Also, I still can't generate a rule without the "-o" currently. That's problematic in the case where a VPN tunnel is generated on occasion, and then you have to manually override the "-o" specs from the ruleset. That doesn't make life easier :-(

    Anyway, you're the project leader and you know my objections. Bear in mind that there might be many people out there with the same problem who just don't report but are annoyed of current behaviour. I'll stop here.

    BTW, the new "negate" icon - the small "x" - is not very clear, it was better before. A big red "!" would be more clear, as "!" is used as "not", while "x" looks like "close this window", and it's rather small.

    Otherwise thanks for the wonderful gui, it's become very nice over the years. :-)

     
  • Vadim Kurland
    Vadim Kurland
    2011-10-17

    I do not necessarily agree with you in that your case is somehow less obvious or more difficult to debug than the case I brought up. In the case with two interfaces two generated rules are also semantically correct, but only one of them ever works. This is also difficult to debug, in its own different way.

    However that is not what I am mostly worried about. The problem for me is that if I just removed "-o" from generated NAT commands that have no interface in the "Interface" column, then generated iptables command would change for people who started using fwbuilder some time ago and relied on this particular behavior. This means, they will see their firewall break after they upgrade, unless they go and manually fix their rules. I can not do this.

    About the last workaround I suggested, where you create a standalone address object with ip address you want to use for source address in translated packets. If you use this standalone object in the Translated Source, generated iptables commands should still have "-o" but it will match all interfaces, like so: "-o tun+". This is equivalent to not having "-o" at all. Even thought this "-o" is redundant, it is going to be hard to remove it because of the way compiler works internally. It should not break anything though since it matches all inetrfaces.

    thanks for the feedback on the "negate" icon, unfortunately this is little too late in the cycle but we should consider changing icons back in the next next release.

     
1 2 > >> (Page 1 of 2)