Scenario / Questions

On Arch Linux, I would like to have eth0 (connected to bridged router) share the connection received from wlan0, I’ve read tutorials but I’m not command savvy as other users are and don’t completely understand.

Find below all possible solutions or suggestions for the above questions..

Suggestion: 1


It is not possible to bridge between wireless (client a.k.a. station mode) and wired interfaces according to this thread on linux-ath5k-devel.

Setup NAT

One should set up NAT instead:

echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE

Assigning an IP

Then you have to assign IP addresses to yourself:

ifconfig eth0 netmask up

Install dhcp daemon

Install a dhcp server and add the following text to its config file (in /etc/dhcpd.conf or something similar)

subnet netmask {
    option routers;
    option domain-name-servers the-ip-address-you-have-in-etc-resolv.conf;

Start dhcpd

Then start it /etc/init.d/dhcpd start

And that’s it!

Only read below if you are interested in the non-working bridging setup

brctl addbr mybridge
brctl addif mybridge eth0
brctl addif mybridge wlan0

First you create a bridge interface I choose an arbitrary name mybridge then add intefaces to it.

You should request a new ip address (This is needed only if you want to get a valid IP for the bridging device itself):

dhclient -d mybridge

Suggestion: 2

To bridge wifi interface you may use iw tool to enable 4addr likewise:

# iw dev <wifiInterface> set 4addr on


# brctl addif <bridgename> <wifiInterface>
can't add <wifiInterface> to bridge <bridgename>: Operation not supported

# iw dev <wifiInterface> set 4addr on
# brctl addif <bridgename> <wifiInterface>

Now it should work. You can show bridges using:

# brctl show

Suggestion: 3

Depends on how mean the AP is to you:

1) It might only want to see packets coming from you, with your known link layer address (and hence not of bridged packets)
2) It might actually be even smarter, and know which IP address should belong to which link layer address (cause it knows DHCP and inspects it)

If 1+2 are both true, you need indeed something like IP NAT, DHCP, ..

But if only 1) is the case, you can fake the link-layer address, and reverse map it onto the right one in the other direction as described here:

Suggestion: 4

4addr as described in other answers is certainly the best way when supported by the adapter/driver, but not all of them does. NAT might work for some things, but getting proper communication both ways on the lan will become problematic (ex. connecting a printer or accessing other IoT devices on the other side of the NAT). Anything relying on broadcast/multicast (ex. auto-discovery, bonjour) will fail through the NAT.

The alternative is using an ARP Proxy (parprouted) as described in I’ve set this up on a Raspberry Pi for a printer and it works like a charm (I have added a 10 second sleep in the post-up commands to let it get an IP address first, it might have to do with the slowness of my old RPi…)

Suggestion: 5

Bridge wlan and 4addr:

Bridging wlan0 is a pain. You normally cannot add it to a bridge interface (brctl returns “Operation not permitted”), and using VirtualBox “bridged” filter results in a big mess of ARP and DHCP conflicts. The cause of this is that 802.11 frames contain only three addresses by default: the MAC addresses of both wireless devices (laptop and AP) and of the final recipient (as in Ethernet). It is always assumed that there is only one possible originator.

802.11 can carry the fourth, originator’s MAC address, and this is used in WDS mode by repeaters. This feature can be enabled on Linux too, using iw, and enabling this mode will allow wlan0 to be used in bridge interfaces, as well as with VirtualBox bridged networking:

iw dev wlan0 set 4addr on

However, with 4addr enabled, you’re likely to get completely ignored by the AP: association succeeds but all data frames disappear into the ether. This could be for security reasons (because it’s damn hard to spoof the source MAC address. Yeah.) In my router (running OpenRG), it’s necessary to enable “WDS” mode for the wireless AP interface, add a WDS device restricted to my laptop’s MAC address, and add it to the LAN bridge. 4addr packets now work.

There’s another problem with this, though – the router now rejects three-address packets from the laptop, which can be rather inconvenient (having to toggle 4addr every time the WLAN network is changed). The workaround is to add, on the laptop, a second wireless interface linked to the same device, but with a different MAC address. First undo the earlier configuration:

iw dev wlan0 set 4addr off

Then, add a second interface – the name was chosen arbitrarily – with a different MAC address:

iw dev wlan0 interface add wds.wlan0 type managed 4addr on
ip link set dev wds.wlan0 addr <addr>
ip link set dev wds.wlan0 up

Here must match the WDS device address configured in the router; other than that, it can be any valid MAC address. The original MAC of wlan0 then remains for “normal” usage.

It’s possible to use both wlan0 and wds.wlan0 at the same time – although I’ve only tested associating to the same AP twice, not to different APs. I’m guessing they would need to at least be on the same channel.

Some people have asked why use this when VirtualBox can bridge WiFi “just fine”. The answer is that VirtualBox does not send the virtual machines’ MAC addresses; rather, it performs NAT at the MAC layer too. – 2014-08-22

Direct wlan bridge

Under certain circumstances, you could also use wlan_kabel. It uses packet sockets to directly bridge wlan*-devices with ethernet devices. However, you can only bridge one single MAC at a time with wlan_kabel. It doesn’t have the drawback of being barred by access points, because only the original MAC of the wlan device is used. In your case this would mean, that wlan0 could only be used by one VM and not even by the host. You can get wlan_kabel here. This is similar to the macvlans solution.

Bridging with ipvlan

IP Vlan does not have the limitation of a bridge it could be used to bridge a network details on how to use it can be found here

Masquerade alternative

Linux routing can be used instead with iptables-masquerade and ip_forward to achieve a bridge but as mentioned this require to enable ip_forward and will make linux act like a router this need to be setup carefully because it could introduce some security concern.

# bridge setup
brctl addbr br0
ifconfig br0 up

# enable ipv4 forwarding
echo "1" > /proc/sys/net/ipv4/ip_forward

# netfilter cleanup
iptables --flush
iptables -t nat -F
iptables -X
iptables -Z
iptables -P INPUT ACCEPT

# netfilter network address translation
iptables -t nat -A POSTROUTING -o wlan0 -s  -j MASQUERADE

The interface br0 will then have access to the wlan0 network

Important and related

Also, and very important, you should not use obsolete, deprecated commands like ifconfig, brctl, and so on. The iproute2 suite contains commands for all of this, including setting up virtual interfaces (something for which we once had to use openvpn) and creating bridges. If you do not know how to set up a bridge with ip, here we go

  ip tuntap add tap0 mode tap user root 
  ip link set tap0 up
  ip link add br0 type bridge
  ip link set tap0 master br0
  ip link set eth0 master br0
  ip addr add  dev br0
  ip link set br0 up

With this set of commands, we create a virtual interface called tap0, then a bridge called br0, then enslave eth0 and tap0 to the bridge, to which we assign an IP address of, then bring it all up. The three separate instances of bringing the interfaces up (for tap0, eth0, and br0) are required.

The trick to make this work is to use proxy.arp, which allows your pc (not your VM/Linux container/network namespace) to answer ARP queries in their stead.

In other words, by using IPv4 forwarding between your hardware interface and your virtual interface, you think you can connect your VM/LXC/NNS to your LAN as if it were a physical interface, but this is not true: you are forgetting the absolutely fundamental ARP traffic, which is what truly allows LAN to operate. So, the problem is: if I correctly forward IPv4 traffic, how can I also forward ARP traffic, so that my VM/LXC/NNS work? The trick is to use proxy-arp.

The full answer to that is in Bohdi Zazen’s Blog, with the revealing title: Bridge wireless cards. He uses an obsolete package, uml-utilities, to create a virtual interface by means of the command tunctl: this is the only command for which he uses uml-utilities, so that you can safely neglect downloading the package, and use the command I wrote above to create a tap or tun interface, whichever you like, just modify the command accordingly. then create a veth pair for your LXC, and now create a bridge between tap0 and veth0. This bridge, called br0, is what you must proxy-arp for, instead of the simple tap0 interface described by Bohdi Zazen.


Suggestion: 6

I liked the Proxy Arp approach, but the original question specified Arch Linux. Here’s an Arch Linux version of a Raspbian implementation. I tried very hard to adapt the original approach from the Debian Wiki mentioned here to netctl using ExecUpPost and ExecDownPre without success. Everything worked at the command line, but not within the profile.

The steps:

  1. Implement wireless networking with systemd-networkd. Within the .network file, set IPForward=yes. I used WPA Supplicant to manage the wireless network interface.
  2. Enable mDNS relaying by setting enable-reflector=yes within /etc/avahi/avahi-daemon.conf; start and enable avahi-daemon.service if it’s not already.
  3. Install parprouted from the AUR, and create a service file for it by adapting the one from the Raspbian answer. I did not find it was necessary to set the interface to be promiscuous. Naturally, this service will need to be started and enabled.
Description=proxy arp routing service

# Restart until wlan0 gained carrier
ExecStartPre=/lib/systemd/systemd-networkd-wait-online --interface=wlan0 --timeout=6 --quiet
ExecStartPre=/usr/bin/echo 'systemd-networkd-wait-online: wlan0 is online'
# clone the dhcp-allocated IP to eth0 so dhcrelay will relay for the correct subnet
ExecStartPre=/usr/bin/bash -c '/usr/bin/ip addr add $(/usr/bin/ip -4 -br addr show wlan0 | /usr/bin/grep -Po "\\d+\\.\\d+\\.\\d+\\.\\d+")/32 dev eth0'
ExecStartPre=/usr/bin/ip link set dev eth0 up

#         v minus sign
ExecStart=-/usr/bin/parprouted eth0 wlan0

ExecStopPost=/usr/bin/ip link set dev eth0 down
ExecStopPost=/usr/bin/bash -c '/usr/bin/ip addr del $(/usr/bin/ip -4 -br addr show eth0 | /usr/bin/grep -Po "\\d+\\.\\d+\\.\\d+\\.\\d+")/32 dev eth0'

  1. To support DHCP for the device connected to the ethernet port, create a dhcrelay (from the DHCP package) service. Finding the address of the DHCP server by grep’ing through logs seems inelegant, but it works. Start and enable.
Description=DHCRelay Service parprouted_bridge.service

ExecStart=/usr/bin/bash -c '/usr/bin/dhcrelay -d -4 -iu wlan0 -id eth0 $(/usr/bin/journalctl -b -u systemd-networkd.service | /usr/bin/grep -Po "via\s+\K\\d+\\.\\d+\\.\\d+\\.\\d+")'


This approach worked for me on a Raspberry Pi Model B+ w/ ArchLinuxArm sporting a USB WiFi adapter with the RT5370 chipset. As the Pi will be providing WiFi to a printer with only ethernet, I’d like it to be robust to rough handling, so my next step will be to configure the SD card as read only.