Linux – Blindly bridging wireless client with MAC NAT

bridgelink-layerlinuxnat;wireless-bridge

This is the usual "I want to bridge wifi with ethernet" question, but I need something specific here.

My Linux box has a wlan0 interface which is in station mode, with MAC aa:aa:aa:aa:aa:aa, and a VLAN interface (vlan0) with MAC bb:bb:bb:bb:bb:bb. Only one specific host is talking to me over the VLAN, so all packets arriving from the VLAN will have source MAC address cc:cc:cc:cc:cc:cc.

And due to the three-address framing in WiFi, all packets arriving from wlan0 will have destination MAC address aa:aa:aa:aa:aa:aa. Is this right, or am I oversimplifying?


What I want to do is a simple MAC NAT bridge, in which:

  1. A packet coming from wlan0 gets its destination MAC changed to cc:cc:cc:cc:cc:cc and blindly sent through VLAN.

    Got from wlan0                       Sent through vlan0
    SRC: whatever it is                  SRC: whatever it is
    DST: aa:aa:aa:aa:aa:aa      -->      DST: cc:cc:cc:cc:cc:cc
    (payload)                            (payload)
    
  2. A packet coming from vlan0 gets its source MAC changed to aa:aa:aa:aa:aa:aa and blindly sent through wlan0.

    Sent through wlan0                   Got from vlan0
    SRC: aa:aa:aa:aa:aa:aa               SRC: cc:cc:cc:cc:cc:cc
    DST: whatever it is         <--      DST: whatever it is
    (payload)                            (payload)
    
  3. Incoming ARP replies from vlan0 also get the ARP MAC updated. Example:

    Sent through wlan0                   Got from vlan0
    SRC: aa:aa:aa:aa:aa:aa               SRC: cc:cc:cc:cc:cc:cc
    DST: whatever it is         <--      DST: whatever it is
    1.2.3.4 can be found at              1.2.3.4 can be found at
    aa:aa:aa:aa:aa:aa                    cc:cc:cc:cc:cc:cc
    

ebtables sounds like the perfect way to do this… if only I could bridge the two interfaces together.
Any idea? I've heard about relayd, could that help?

Best Answer

I know this is an old question, but I needed to solve exactly this problem and had to spend a few days figuring out the best way to solve it. https://xkcd.com/979/

Let's name the interfaces on Linux box A (wlan0), B (vlan0) and the client host C (vlan0). So you need something like a bridge of A and B (wlan0 and vlan0), except you can't bridge these interfaces in Linux (and WiFi STA wouldn't make C work anyway).

What I ended up doing and confirmed it working:

  • changed C (client vlan0) MAC address to the same as A (host wlan0)
  • cleared IP addresses of A, B and C
  • wrote a daemon to move ethernet frames between A and B

The daemon opens raw sockets to read from both A and B, filter and push to the other interface. The catch is to filter based on source MAC address to avoid loops (outgoing must be the same as wlan0, incoming must not be wlan0's).

That's it. ARP, DHCP, ping and HTTP just works.

Related Topic