0

I currently have set up IPTables on my server to forward certain ports on a specific interface (venet0:1) to a second server, at a different IP. My config file looks like this:

# Generated by iptables-save v1.4.12 on Sat Jun  8 08:36:54 2013
*mangle
:PREROUTING ACCEPT [480:39372]
:INPUT ACCEPT [480:39372]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [339:44328]
:POSTROUTING ACCEPT [339:44328]
COMMIT
# Completed on Sat Jun  8 08:36:54 2013
# Generated by iptables-save v1.4.12 on Sat Jun  8 08:36:54 2013
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A PREROUTING -i venet0:1 -p tcp -m state --state NEW,RELATED,ESTABLISHED -m tcp --dport 51315 -j DNAT --to-destination 76.xxx.xxx.xxx
-A PREROUTING -i venet0:1 -p tcp -m state --state NEW,RELATED,ESTABLISHED -m tcp --dport 27015:27020 -j DNAT --to-destination 76.xxx.xxx.xxx
-A PREROUTING -i venet0:1 -p tcp -m state --state NEW,RELATED,ESTABLISHED -m tcp --dport 25565:25570 -j DNAT --to-destination 76.xxx.xxx.xxx
-A PREROUTING -i venet0:1 -p tcp -m state --state NEW,RELATED,ESTABLISHED -m tcp --dport 7777 -j DNAT --to-destination 76.xxx.xxx.xxx
COMMIT
# Completed on Sat Jun  8 08:36:54 2013
# Generated by iptables-save v1.4.12 on Sat Jun  8 08:36:54 2013
*filter
:INPUT ACCEPT [86:6572]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [66:6912]
-A INPUT -i venet0:1 -j LOG
-A INPUT -i venet0:1 -p tcp -m tcp --dport 51315 -j ACCEPT
-A INPUT -i venet0:1 -p tcp -m tcp --dport 27015:27020 -j ACCEPT
-A INPUT -i venet0:1 -p tcp -m tcp --dport 25565:25570 -j ACCEPT
-A INPUT -i venet0:1 -p tcp -m tcp --dport 7777 -j ACCEPT
COMMIT
# Completed on Sat Jun  8 08:36:54 2013

(IP addresses concealed)

I've made sure that IPv4 forwarding is enabled, however when I do a lsmod, nothing at all shows up.

I've also tried using modprobe to add the iptables kernel modules, but nothing is found.

Could it be that the IPTables modules simply aren't installed, and that I need to recompile the kernel to install them?

When I try to connect on those ports, the connection is refused, as if iptables isn't even running.

I'm running Ubuntu 12.04 LTS on an OpenVZ VPS (hostname isn't actually hostname).

Linux hostname 2.6.32-042stab076.7 #1 SMP Thu Apr 25 13:35:47 MSK 2013 x86_64 x86_64 x86_64 GNU/Linux

EDIT: OK, at the suggestion of one of the answers, I changed venet0:1 to venet0. The behavior is still the same. A tcpdump of the port shows the following:

23:15:34.940437 IP 76.yyy.yyy.yyy.53802 > 192.xxx.xxx.xxx.51315: Flags [S], seq 3804882566, win 65535, options [mss 1460,nop,wscale 0,nop,nop,sackOK], length 0
23:15:34.940485 IP 76.yyy.yyy.yyy.53802 > 76.xxx.xxx.xxx.51315: Flags [S], seq 3804882566, win 65535, options [mss 1460,nop,wscale 0,nop,nop,sackOK], length 0

In the above, 76.yyy.yyy.yyy is the computer I am using to test the connection, 192.xxx.xxx.xxx is the IP of the server, and 76.xxx.xxx.xxx is the address of the server it's supposed to forward to. It seems to be forwarding the traffic somehow, except that the packets are zero-length and never get replied to. I also ran tcpdump on the receiving machine, and nothing showed up.

Eli
  • 395
  • 3
  • 7
  • 15

2 Answers2

1

I've made sure that IPv4 forwarding is enabled, however when I do a lsmod, nothing at all shows up.

lsmod only show the loaded modules. This has little to nothing to do with iptables. iptables automatically loads the modules it needs during rule insertion, and if it fails, it informs you with a beautiful error message. If your rules are loaded successfully, iptables is running and no modules are missing.

Also, it is perfectly fine to have lsmod shows nothing: it means that the functionality is compiled builtin into the kernel. so the output of lsmod is completely irrelevant here.

When I try to connect on those ports, the connection is refused, as if iptables isn't even running.

-A PREROUTING -i venet0:1 -p tcp -m state --state NEW,RELATED,ESTABLISHED -m tcp --dport 51315 -j DNAT --to-destination 76.xxx.xxx.xxx

The problem here is most likely venet0:1, which does not exist. iptables has this limitation that it accept any interface name, even not existent ones or strings that do not even look like an interface name (you can even put IP addresses, just for fun, it won't work). If there is no interface matching the given name, the rule will simply not match. This is useful when your network interfaces are not yet ready, or if your network interfaces are hot-plugged, but most of the time, it's a pain to not being able to validate that the interface name actually exist. it's so easy to make a typo.

instead, use:

-A PREROUTING -i venet0 -p tcp -m state --state NEW,RELATED,ESTABLISHED -m tcp --dport 51315 -j DNAT --to-destination 76.xxx.xxx.xxx

Now, you will likely reply "but venet0:1 exist, ifconfig shows it !".

Except ifconfig is wrong. The reason ? Linux's ifconfig is old, deprecated, obsolete and sucks. Use ip addr instead. Same for route, netstat and brctl and probably others. ip replace all of them.

ip addr do not fake or hide any information from the kernel. What you see is the real state of the network stack. Now you can see that there is no such venet0:1 interface. Instead, venet0 has several IP addresses. This is something that have been supported since the Linux 2.2 days.

But ifconfig (or actually, the BSD API it uses to communicate with the kernel) do not support that an interface has several IP addresses. So instead you have this old BSD trick called "interface aliases" where you can use ifconfig venet0:1 to configure an additional IP address for venet0, and it will show up as a venet0:1 interface. Except venet0:1 is not an interface. Not even close.

Actually, ip addr will show you that venet0:1 is a label for an IP address, with the manual page telling you:

In order to preserve compatibility with Linux-2.0 net aliases, this string
must coincide with the name of the device or must be prefixed with the
device name followed by colon.

And the iptables manual page used to tell you to not use interface aliases or anything with a colon in it, but that line must have been disappeared.

BatchyX
  • 902
  • 4
  • 7
  • OK, I've changed it from `venet0:1` to `venet0`, and it still has the same behavior. None of the forwarded ports seem to be getting to the host they are supposed to be forwarded to. I've put some more info in the original post – Eli Jun 08 '13 at 19:14
0

About the nat table

You can read this in the iptables man page:

This table is consulted when a packet that creates a new connection is encountered.

So you don't have to check the state of your connection there as this table is checked only for NEW connections.

Let's talk about your problem

OpenVZ is a "virtualization" technology based on namespaces.

Basically, your virtual machine is a simple folder in which a Linux system tree has been set up and contained to give you the illusion of being in a truly independent system. The originality of this virtualization method is that all containers are running one and only one Linux kernel instance, the host's one.

Now you have a problem because as you don't run your own kernel instance, you don't have full control and this explains a lot of things.

  • lsmod is empty because for safety reasons, they won't let you know which modules are running the system and of course, they won't let you change the system configuration by adding new modules. Imagine each client modifying the same kernel running other clients.

  • Even though you can allow the use of iptables for the containers, nat may haven't been enabled.

Spack
  • 1,604
  • 15
  • 22