Following a gateway / firewall system's hardware failure, a younger version of Fedora Core (17) was installed on new hardware, and the old 'iptables' and system-config-firewall files from /etc/sysconfig were used (and nothing else). Old version of FC is unknown but it was probably 14 or 15, old disk is no longer readable. (I've put the former iptables file contents below.)

This systems' job is EXCLUSIVELY to:

  1. Accept port 22 (ssh) from any network source for local delivery (sshd).
  2. Forward port 222 to port 22 (ssh) on an internal system, retaining the originating IP address.
  3. Forward port 25 (email) to an internal system, retaining the originating IP address.
  4. Forward all (non port 22) inbound traffic from the internal network to the external one, applying NAT / Masquerading along the way, and permitting associated externally generated return packets to pass through, as appropriate.

The steps outlined above are the ONLY job of this box and it was formerly working fine.

Where I started:

When returned to service, all connections to port 22 (sshd) work fine, and external connections to all other ports forward through or are dropped as appropriate, but the IP address seen by internal systems was that of the gateway rather than retaining their source IP address.

When I put the system on the wire, all heck breaks loose regarding email; the mail server system behind the gateway is rejecting mail based on IP address / system name mismatches, and eliminating the check makes the spam filter system go crazy.

Was MASQUERADING wrong interface BUT...

Sharp eyed serverfault participant DavidSchwartz noted that masquerading was turned on for the INTERNAL interface (via -A POSTROUTING -o eth0 -j MASQUERADE), explaining the internal systems seeing the gateway IP address, BUT when changed to reflect the external interface (eg: -A POSTROUTING -o eth1 -j MASQUERADE), then ALL FORWARDING STOPS! Yes, I do mean port forwarding, from the external to the internal (port 222 to port 22 on an internal system).

I really don't understand that.

For clarity, it appears that having masquerading turned on for the INTERNAL interface, while not what was intended, DOES have the positive attribute of permitting port forwarding to actually happen from the outside to the inside. Switched to be masquerading the (correct) EXTERNAL interface somehow disables port forwarding as there were NO other changes.

SNAT vs Masquerading

As there are two external facing "server systems" that also have internal interfaces which had been configured to be alternative out-bound paths, I looked at them and found they had a very different masquerading technique; there was no line like that quoted two paragraphs above, but rather this instead:

-A POSTROUTING -s -o eth0 -j SNAT --to-source <external.v4.ip.addr>  

Great - I understand it, makes sense, I try that! I commented out the MASQUERADE line and included (in the same position) a SNAT line as noted here, and YAY! It did two things:

  1. I get outbound network address translation as desired, and;
  2. It now port-forwards inbound connect requests to port 222 from the outside to port 22 on an internal system, retaining the originating IP address as desired.

Remaining Problem

What does not work is the otherwise identically forwarded port 25 (which is to remain port 25 on the internal system).

Presently THIS is the problem I must solve! (And the Sooner The Better!) Why does the one port forward and not the other? Is it not a 'tcp' type port, and if not, what should replace it? (I didn't think it was UDP...)

Less important; it'd be nice to know why the old configuration worked but it won't now! Differences in Fedora Core? Updates to IP tables? Was I relying on bugs? -smile-

Here are the two port-forwarding lines in iptables:

-A PREROUTING -i eth0 -p tcp --dport 25 -j DNAT --to-destination
-A PREROUTING -i eth0 -p tcp --dport 222 -j DNAT --to-destination

I tried it with and without the trailing ":25" on the upper one. Again, external port 222 forwards to internal system port 22 just fine, port 25 does not forward at all.

Note that telnet access to port 25 from a system that can see the mail server system directly (not through a gateway / firewall) works perfectly. Also, I tried forwarding port 24 to port 25 as a test and got the same result (no response).

Here's the iptables file:

# eth0 is internal
# eth1 is external


# NO packets get through without this next line:
# the above line was commented out and replaced with:
-A POSTROUTING -s -o eth0 -j SNAT --to-source <external.v4.ip.addr>

-A PREROUTING -i eth1 -p tcp --dport 25 -j DNAT --to-destination

-A PREROUTING -i eth1 -p tcp --dport 222 -j DNAT --to-destination

-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth0 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT

-A INPUT -m state --state NEW -m tcp -p tcp --dport 25 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 222 -j ACCEPT

-A FORWARD -p icmp -j ACCEPT
-A FORWARD -i eth0 -j ACCEPT
-A FORWARD -o eth0 -j ACCEPT
-A FORWARD -i eth1 -m state --state NEW -m tcp -p tcp -d --dport 25
-A FORWARD -i eth1 -m state --state NEW -m tcp -p tcp -d --dport 22

-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
  • Are you sure you have the correct interface name? If you've freshly installed a recent version of Fedora, you will probably have interfaces using the new consistent naming scheme. – Michael Hampton Jan 30 '13 at 22:47
  • @MichaelHampton Yes, I think so: I cut and pasted from "ifconfig" output. Shouldn't that do it? – Richard T Jan 30 '13 at 22:50
  • @MichaelHampton MAYBE YOUR HUNCH WAS CORRECT: after more hours than I'd like to admit trying to get this system working correctly, I've come to think that maybe you are on to something. Here are some other thoughts: serverfault.com/questions/474449/… Any suggestions? – Richard T Feb 1 '13 at 5:08
  • So your interfaces are named em1 and p4p1? That's really easy then. Just change your scripts to match. – Michael Hampton Feb 1 '13 at 5:17
  • @MichaelHampton ...I'm not that dumb / ignorant / etc; I of course have been trying that for days. No joy. My suspicion is that the name I see from ifconfig isn't the same as what iptables wants to use. I sourced up another system that's older and doesn't have the name issue and it at least port-forwards correctly - except for port 25 and I'm not sure why (it doesn't have sendmail, etc)... – Richard T Feb 1 '13 at 5:20

You asked it to masquerade traffic going out the internal interface, so that's what it's doing. Masquerading means to impersonate the source of the connection. Remove this line and, if something breaks, add the correct rule.

  • Thanks, David, ... I feel sooooooo silly! BUT, when I do that - eliminate the rule or change it to the actual OUTBOUND interface - no packets get passed at all. Any suggestions? – Richard T Jan 31 '13 at 4:09
  • Add rules to handle the packets you want to handle. What specific packets don't pass? (Are you talking about NAT that doesn't happen? Or just routing that doesn't happen?) If you want to masquerade outgoing packets to the internet with local sources, then do that. – David Schwartz Jan 31 '13 at 4:10
  • Sorry; connections from the external interface should be either explicitly forwarded to the internal interface (as outlined above, ports 222 and 25) or are either locally accepted (only 22) or rejected. All connections from the internal interface should either be locally accepted (only port 22) or masqueraded on the external interface. This same set of rules was formerly doing just that, except for any errors I just introduced. Thanks for your thoughts / observations. – Richard T Jan 31 '13 at 4:28
  • @RichardT: Where's the rule to masquerade connections from the internal interface to the external interface? The rule you have masquerades -o eth0. – David Schwartz Jan 31 '13 at 4:35
  • Sorry again - I must be TERRIBLE at communication today: On your observation I switched the interfaces used in that statement, from -o eth0 to -o eth1 and THAT is when "no packets get passed at all." So when you ask "where's the rule", my answer is that I just switched interfaces - isn't THAT what was my error?!?! CLEARLY the original script had one or the other - I didn't do a damned thing to it (knowingly). Sorry to be less than clear; NEITHER masquerade works as hoped: one passes zero (no forwards), the other forwards but masquerades the wrong direction. – Richard T Jan 31 '13 at 4:48

I FINALLY solved this.

Well, actually I gave up on it and found the answer while working on a different problem.

The answer is: The internal receiving system MUST use the same return route - same gateway / firewall system - for the port forwarding to work correctly! At least this is true for SMTP. It does not appear to be true for some services like ssh, but confirmed by behavior, SMTP (in my case Postfix) won't work correctly if the default route is other than the system that forwarded the connection.

This has implications for those of us who want redundancy - I'd like the mail server to be able to revcieve forwarded ports from more than one gateway / firewall. I have yet to figure out how to create special routes for this multiple gateway / firewall strategy, but I understand iptables can do it.

Good luck out there!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.