Linux Containers: Part 4, Getting to the Universe (Ping Google.com)

E

Eric Hansen

Guest
I know I mentioned this part would cover templates and how to make your own, but truthfully getting your existing container to connect to the network (both internally and externally) seems more important, no? This was also something I over-compensated for but the past few days have really taught me something.

In this part we’ll get it to connect to the network and make it so you can ping Linux.org. Then, the next part will be a cover of setting up OpenVPN so you can use your new container for a VPN tunnel (I spent a good week trying to get this to work, but it feels great now that it does!).

We will be continuing off from the last part so make sure you’ve read those before this one.

Setting an IP Address
While IPv6 is workable (at least in theory) in a container, we’ll be focused only with IPv4. So lets go to our /var/lib/lxc/linux_org directory and open up the config file in our editor (I use nano, feel free to use vi/vim, it doesn’t matter).

You’ll notice at the start some lines that look like this:
Code:
lxc.network.type=veth
lxc.network.link=lxcbr0
lxc.network.flags=up
lxc.network.hwaddr = 00:16:3e:42:1d:a7
lxc.utsname = linux_org

Setting the Adapter Name
This default configuration above will simply generate a random adapter name (i.e.: veth3VcOob). This is fine if you’re only going to be using one container. However, if you plan on creating and operating multiple containers at once then you’re most likely going to want a more descriptive name. How about we name it “vethlinuxorg”? Add this line to the above block:
Code:
lxc.network.veth.pair = vethlinuxorg

Picking an IP Address
We want one that isn’t going to be used. Since I’m a fan of the number 42, we’ll use 10.0.3.42 for this container. Lets tell the container to use this by adding this line:
Code:
lxc.network.ipv4 = 10.0.3.42

Now, some will say to add a subnet as well (i.e.: /24) to the end of it, I’ve never noticed any issues by not doing that, so we’ll not worry ourselves.

Enable the Changes
After making these changes you will have to restart the container. There is the lxc-restart command, but that doesn’t want to work for me. So we’ll do it the slower way:
Code:
lxc-stop -n linux_org
lxc-start -n linux_org -d

Remember, the “-d” command starts the container in the background so lxc-console will let us play more nicely with it.

Now, a couple of things for us to do to make sure our changes took effect. The first is to see if the adapter exists. I have to run ip addr but you might have luck still using ifconfig, depending on if your system uses systemd or sysv. Either way you should see an entry for vethlinuxorg. In that same block you should also see the IP 10.0.3.42. If not, review the configuration settings.

Pinging the Local Network
Right now console into the container and log in. For the sake of clarity sudo su - as well. Try to ping 10.0.3.1. I expect you to get something like this (“-c 1” just specifies sending 1 ping request then finish):
Code:
root@linux_org:~# ping -c 1 10.0.3.1
PING 10.0.3.1 (10.0.3.1) 56(84) bytes of data.
64 bytes from 10.0.3.1: icmp_req=1 ttl=64 time=0.226 ms
--- 10.0.3.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.226/0.226/0.226/0.000 ms
This is good news! Lets see if we can ping outside of our container. Since the ultimate goal is Google, lets get straight to that one (“-W 10” states that we want to wait only 10 seconds for a response, if we don’t get one then assume we won’t receive a response).
Code:
root@linux_org:~# ping -c 1 -W 5 google.com
PING google.com (173.194.43.3) 56(84) bytes of data.
--- google.com ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

Why doesn’t this work, you ask?

Well, lets take a step back and look at how our network is set up. We have the host, which is essentially a switch and router when it comes to LXC. Then we have the containers which are devices within its own network. The reason we can connect to anything within the LAN is because the host/router has a route set up to forward 10.0.3.0/24 traffic to 10.0.3.1 which then directs it to the proper machine. Having this set up on the router, however, for an external source is a little bit trickier, especially when the remote machine’s IP can change at any given point.

For this, we need to use iptables on the router/host. So lets get out of the console by doing ctrl+a then ctrl+q, you should now be dropped back into the host’s shell. Install iptables if you haven’t yet (apt-get install iptables if you’re on a Debian/Ubuntu based system).

Without going into all the technical details of iptables and such, we want to be working with the NAT (network address translation) table, so our host/router knows how to handle incoming and outgoing data from our containers. Since we’re not expecting incoming data right now we won’t worry about that, just being able to reach the outside network. This falls into the POSTROUTING chain in the NAT table.

Small background, iptables operates in what is called tables (the default is “filter”, “nat” is used for performing routing). In each table there’s “chains” or groups of rules that you can specify and they operate in a top-down approach. The appropriate flow of outgoing data through iptables is this:
Code:
NAT table (postrouting chain -> output chain) -> FILTER table (output chain)

One would think we need to work on the output chain in the FILTER table, but that is actually not true. We want the postrouting chain in the NAT table. To make a long story short, there’s two options here: MASQUERADE and SNAT.
  • SNAT - use this if the destination of the packet’s IP address doesn’t change (rarely that lucky)
  • MASQUERADE - use this to not care if the IP address changes (lazy person’s method)
You’ll usually see MASQUERADE used for situations where we need to route traffic from our LAN to outside of the network, and this guide is going to be no different. Use the following iptables command:
Code:
iptables -t nat -A POSTROUTING -s 10.0.3.0/24 -o eth0 -j MASQUERADE
This basically sets up a firewall rule to send all traffic from 10.0.3.0/24 to our Internet adapter (i.e.: eth0 can reach the Internet) without specifying a specific destination.

After you do this go back into the container’s console and run the ping command again:
Code:
root@linux_org:~# ping google.com -c 1 -W 10
PING google.com (173.194.43.3) 56(84) bytes of data.
64 bytes from lga15s34-in-f3.1e100.net (173.194.43.3): icmp_req=1 ttl=55 time=26.7 ms
--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 26.794/26.794/26.794/0.000 ms
Now we’re able to connect to Google without any issues!
 

Attachments

  • slide.jpg
    slide.jpg
    26.6 KB · Views: 86,535

Members online


Latest posts

Top