Since you can’t bridge a wireless NIC, you’ll need to create a new bridge for your containers, set up NAT through it to the wireless NIC, and set up dnsmasq to provide ip addresses to your containers. First make sure we have the tools create and configure the bridge and provide dhcp to the containers:
apt-get install bridge-utils dnsmasq-base
and make sure that forwarding is turned on to support NAT:
echo 1 > /proc/sys/net/ipv4/ip_forward echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
Now create the bridge, as usual, using /etc/network/interfaces:
auto lxcbr0 iface lxcbr0 inet static address 192.168.30.1 netmask 255.255.255.0 post-up /opt/bin/lxcbr0-up
That entry says that when the bridge comes up, run /opt/bin/lxcbr0-up. Create that file, open it with your favorite editor, and paste in:
#!/bin/sh # This is the address we assigned to our bridge in /etc/network/interfaces braddr=192.168.30.1 # ip address range for containers brrange=192.168.30.2,192.168.30.254 iptables -A FORWARD -i lxcbr0 -s ${braddr}/24 -m conntrack --ctstate NEW -j ACCEPT iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A POSTROUTING -t nat -j MASQUERADE dnsmasq --bind-interfaces --conf-file= --listen-address $braddr --except-interface lo --dhcp-range $brrange --dhcp-lease-max=253 --dhcp-no-override
Make sure it is executable by doing
chmod ugo+x /opt/bin/lxcbr0-up
Bring up the bridge:
ifup lxcbr0
My lxc.conf now reads:
lxc.network.type=veth
lxc.network.link=lxcbr0
lxc.network.flags=up
And you can create containers as always using
lxc-create -t natty -f /etc/lxc.conf -n natty1
There are some different games you can play by turning stp on, but that's not for this post.
Thanks so much for posting these instructions!
The only adjustment I needed to make to get this to work for me on Ubuntu 11.10 amd64 CLI, was to add the following line before the post-up line in /etc/network/interfaces .
pre-up brctl addbr lxcbr0
Would this work is I am not using the lxcbr0, but just using br0 since I have that in place to handle KVM guests as well?
If you already are using a br0 for your kvm guests, then you can simply use it for your containers without any changes to the bridge.
I made the following change to /etc/network/interface:
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet manual
auto wlan0
iface wlan0 inet manual
auto br0
iface br0 inet dhcp
bridge_ports wlan0
bridge_stp off
bridge_fd 0
bridge_maxwait 0
When I reboot with this change, NetworkManager fails to start and even after I force start of Network Manager, my lxc container fails to start. Currently, I have my /etc/network/interfaces setup like this:
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet manual
auto br0
iface br0 inet dhcp
bridge_ports eth0
bridge_stp off
bridge_fd 0
bridge_maxwait 0
Of course, that requires that I have a wire plugged into the machines. I have not made any changes to my /etc/lxc/lxc.conf since I was unsure of it should be changes to.
kcc@gallifrey:~$ cat /etc/lxc/lxc.conf
lxc.network.type=veth
lxc.network.link=br0
lxc.network.flags=up
Right, you cannot bridge a wireless nic.
You so are saying that I am destined to always be plugged into a cable?
No, you just have to forward the traffic as is done with lxcbr0.
Then I must be missing the information on how to do the forwarding… Is that in your blog or was it somewhere else?
Ok, I did see it on your site. I have my container getting it’s address from my router. Do I need to still set up DNSMASQ on my host or could I do the iptable changes on the router (which is a DD-WRT based router). Of course, now that I look at the look at your script, I realize that my router would not know anything about the my bridge on my host.
So I need to actually setup DNSMASQ and do port forwarding on my host, although I can still let my router assign the IP address, if I am reading this right and thinking this through.
It depends on what you want. If you’re happy with the router giving your container the address, then yeah you can just have the router forward whatever ports you want. Have fun! 🙂
Couldn’t I do the ip forwarding on the host, apply the iptables entries and still allow my router to pass the ip address?
Yup there are lots of ways you can set it up. But there will have to be rules on the router to forward traffic to either the host (to then be fwded from there) or straight to the container.
You need to add the following line to your script otherwise DHCP will fail in a Debian Wheezy guest with “5 bad udp checksums in 5 packets”:
pre-up iptables -t mangle -A POSTROUTING -p udp –dport bootpc -s 10.0.0.1 -j CHECKSUM –checksum-fill
More details at https://github.com/fgrehm/vagrant-lxc/issues/153 and https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/930962
Thanks – really I consider it a bug both in the kernel and dhclient (and showed up long after this blog post) but thanks for commenting, I bet it’ll save others some frutration 🙂
Thanks for this post. Know it’s old, but still relevant. NAT has just been added to systemd-networkd, but it won’t trickle down for awhile. Thought I would post an upgraded script that works. Includes DHCP checksumming fix, and works with archlinux, and doesn’t create redundant rules.
“`
# Interfaces
WAN={{ wan_interface | eth0 }}
LAN={{ bridge_interface | br0 }}
# Addresses
LAN_IP={{ bridge_ip | 10.0.10.1 }}
LAN_SUBNET={{ bridge_subnet | 10.0.10.0/24 }}
DHCP_RANGE={{ bridge_dhcp_range | 10.0.10.2,10.0.10.254 }}
# FIREWALL RULES
iptables -A POSTROUTING -t nat -o $WAN -j MASQUERADE
iptables -A FORWARD -m conntrack –ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -s ${LAN_SUBNET} -o $WAN -j ACCEPT
# fix DHCP checksumming
iptables -A POSTROUTING -t mangle -p udp –dport bootpc -s ${LAN_SUBNET} -j CHECKSUM –checksum-fill
# masq DHCP server
dnsmasq –bind-interfaces –conf-file= –listen-address ${LAN_IP} –except-interface lo –dhcp-range ${DHCP_RANGE} –dhcp-lease-max=253 –dhcp-no-override
“`
Why use NAT over simple IP forwarding?
How does all of this work under systemd-networkd?
Hi , i tried this , but when it come to the command”ifup lxcbr0″, it show the massage ” cannot find device “lxcbr0″
Failed to bring up lxcbr0”
what did i missing? i set up lxcbr0 in /etc/network/interfaces the same way, also created lxcbr0-up in
/opt/bin/, it sill says “cannot find device”…. any advice? thanks!
i think i just solved it, i just added ” bridge_ports none ” in /etc/network/interfaces, like this:
auto lxcbr0
iface lxcbr0 inet static
address xx.xx.xx.xx
netmask 255.255.255.0
post-up /opt/bin/lxcbr0-up
bridge_ports none # <— i put it here
and boom, i see everything works perfect, now i see a ip address shows up in my container, and i can ping 8.8.8.8 ( google's server for example ) and no package loss, nice! my container really connected to the internet, thank you for sharing this , i just try to solve the container's internet problems for several days, im so happy after solving this problem! Anyway, thanks again!