I am using Raspberry Pi using Raspbian which is just Debian.

I would like to bridge from the primary WiFi network router that connects to Cox Cable to my cabled router here for my subnet to have reliable internet access.

It needs to be a WiFi-to-Ethernet bridge.

I have set /etc/networks for a static address for the USB wlan1 with the external adapter and hi-gain antenna. wpa_supplicant is configured to log in to the master router properly.

So right now it is set up so I can login to the proper network with the password, on external wlan1. Static address is set in /etc/networks. Gateway and nameserver are OK. I can browse web pages, etc.

The missing link is to bridge this to the eth0 port so my router can connect also, to provide service to my subnet.

No need for any extra network services like routing or nat or dhcp, etc. Just a simple bridge.

Can anyone please point me in the right direction to make this happen?

  • Did you try a very basic bridge by setting no IP on your Ethernet device, creating a bridge with brctl addbr br0, adding both devices to the bridge with brctl addif br0 device, and then setting your original Ethernet address and route on br0? – Julie Pelletier May 6 '17 at 0:35
  • You have not documented how your wlan0 is configured atm. – Rui F Ribeiro May 6 '17 at 8:42
  • Good point. I added some edits to clarify. I like your answer below. It is precisely the opposite of what I am trying to do, but that's OK because I think it is enough information to get me moving. Thank you for posting it. – SDsolar May 6 '17 at 17:25
  • Found this one and the first answer is funny. 'too broadly correct' - so this bridging stuff apparently requires magic, also. unix.stackexchange.com/questions/272146/… – SDsolar May 8 '17 at 23:13
  • Update from the future (late 2018): Since 2.6.33, you can't bridge wlan to eth. You can bridge wlan to eth only if you switched then wlan0 into 4addr mode. Not all drivers support that. You can read more about it here. – peterh - Reinstate Monica Dec 13 '18 at 11:46

For configuring a bridge from ethernet to wifi, it is as simple as doing in your /etc/network/interfaces:

auto eth0
allow-hotplug eth0
iface eth0 inet manual

auto wlan0
allow-hotplug wlan0
iface wlan0 inet manual

auto br0
iface br0 inet static
bridge_ports eth0 wlan0

Replace the IP address with something more appropriate to your network.

If you prefer the IP attribution done via DHCP, change it to:

auto br0
iface br0 inet dhcp
bridge_ports eth0 wlan0

After changing /etc/network/interfaces, either restarting Debian or doing

service networking restart

Will activate this configuration.

You will have to make sure for this configuration to have bridge-utils installed. You can install it with:

sudo apt install bridge-utils

For more information, see:


The wlan0 interface also has to be condigured to connect to your remote AP so this configuration is not be used verbatim.

Additional note: bridging eth0 and wlan0 together means in poor layman´s terms that br0 will present itself as a single logical interface englobing the interfaces that make part of the bridge. Usually such configuration is made when both extend or belong to the same network.

  • It is not actually the opposite; if you want wifi clients to connect to the raspberry you need hostapd on top of this configuration; I actually have an openwrt that has been configured here to do what you are asking – Rui F Ribeiro May 6 '17 at 17:50
  • It is simpler than, it is a matter of configuring the wpa_supplicant – Rui F Ribeiro May 6 '17 at 19:54
  • OK. Right now it is set up so I can login to the proper network with the password, on external wlan1. Static address is set in /etc/networks. Gateway and nameserver are OK. It logs in to the router perfectly. I can browse web pages, etc. The missing link is to bridge this to the eth0 port so my router can connect also. – SDsolar May 7 '17 at 20:11
  • 4
    I'm a little bit confused. If I try your setup and do sudo ifup -a I get the error message can't add wlan0 to bridge br0: Operation not supported. This was widely discussed with Bridging wlan0 to eth0. What I'm missing with your setup? – Ingo Feb 28 '18 at 20:00
  • 2
    No problem to open a new question but I'm unsure if it make sense. I think your answer is outdated and should be corrected. Since kernel >=2.6.33 you cannot add wifi to a bridge (except when WDS is used). This is what is discussed in Bridging wlan0 to eth0. – Ingo Feb 28 '18 at 21:28

I am told that, for those of us who have advanced hardware and firmware, the above bridge solution works. But for me, using open source linux firmware ath9k combined with an open source atheros qualcom chip set, the above answer does not work. So, if you try the bridge and you get the 'Operation Not Permitted' error...

WiFi and Ethernet cannot be directly bridged because the package protocols are different. WiFi assumes that every packet comes from another source and includes that information while Ethernet does not. Spoofing/cheating methods exist, but they will be recognized as a threat by the outside world and blocked.

You must create a local network and masquerade packages through it via iptables to properly convert between the two package types and create fully legitimate WiFi packet addressing via Network Address Translation. The above accepted answer saying that the WiFi and Ethernet can be directly bridged is beyond wrong.

This is a bash program with far to many comment lines which creates a WiFi to Ethernet 'bridge':

# wifi2eth
# Share Wifi with Eth device
# problem: brctl says 'Operation Not Permitted'
# reason: package addressing between Ethernet and Wifi are distinct.
#   Ethernet: Sends its IP as the package source.
#   Wifi: Sends the previous source IP plus its IP as the sources.
# problem: direct bridges are viewed externally as spoofing and rejected for security reasons.
#   Wifi's two source IPs must both be legal and should not be the same or zero.
# need: Network Address Translate packages for proper package modification.
# preliminary: see/create /etc/wpa_supplicant/wpa_supplicant.conf and get your wireless working
# package needed: sudo apt-get -y install dnsmasq # lightweight DNS forwarder and DHCP server

# Step 1: Create the iptables

aEthernet="enp5s0" # the Ethernet output I want for magicJack
aWireless="wlp14s0" # the functioning wireless input
aNext=192.168.2 # the next subnet after 192.168.1
aIp_address="$aNext.1" # use the next subnet to create internal network
aNetmask="" # the network mask
# aNetwork="$aNext.0" # the external inet representing the internal block
# aBroadcast="$aNext.255" # the broadcast IP
aDhcp_range_start="$aNext.0" # inet addresses to be available in subnet
aDhcp_range_end="$aNext.100" # inet addresses to be available in subnet
aDhcp_time="12h" # address lease duration

sudo iptables --flush
sudo iptables \
    --append FORWARD \
    --in-interface $aWireless \
    --out-interface $aEthernet \
    --match state --state RELATED,ESTABLISHED \
    --jump ACCEPT
sudo iptables \
    --append FORWARD \
    --in-interface $aEthernet \
    --out-interface $aWireless \
    --jump ACCEPT
sudo iptables --table nat --flush
sudo iptables \
    --table nat \
    --append POSTROUTING \
    --out-interface $aWireless \
    --jump MASQUERADE

# The iptables language:
#   iptables understand ipv4 (ip6tables understand ipv6 (not used))
#   apt-get install iptables # comes preinstalled with debian
#   An iptable stores a chain of rules which redirects packets.
#     The first match in a chain determines the packet destination. 
#   The iptables table name determines when and how the table is used.
#     An iptables name is not random or arbitrary.
#   --table 'filter' is the default and is for firewall creation
#   --table 'mangle' is for chaning packet headers (TTL values...)
#   --table 'nat' is for routing packets to different hosts via Network Address Translation
#   --table 'raw' is a stateful firewall (knows if packet is part of a new or existing connection...)
#   Chains of a table determine the inspection point.
#     PREROUTING chain is for arriving packets in tables 'nat', 'mangle' and 'raw'.
#     INPUT is chain for packets going to local process in tables 'mangle' and 'filter'.
#     OUTPUT is chain for packets from a process in tables 'raw', 'mangle', 'nat', and 'filter'.
#     FORWARD is chain for packets routed through localhost in tables 'mangle', 'filter'.
#     POSTROUTING is chain for exiting packets in tables 'nat', 'mangle'.
#     MASQUERADE chain...
#       When it receives a datagram from a computer on the LAN
#         it takes note of the type of datagram it is, "TCP," "UDP," "ICMP," etc.
#         and modifies the datagram so that it looks like it was generated by the router machine itself
#         and remembers that it has done so.
#       It then transmits the datagram onto the Internet with its single connected IP address.
#       When the destination host receives this datagram,
#         it believes the datagram has come from the routing host and sends any reply datagrams back to that address.
#       When the Linux masquerade router receives a datagram from its Internet connection,
#         it looks in its table of established masqueraded connections
#         to see if this datagram actually belongs to a computer on the LAN,
#         if it does, it reverses the modification it did on the forward path
#         and transmits the datagram to the LAN computer.
#   The target of a rule defines what happens to matched packets.
#     ACCEPT is the default which forwards or allows the packet.
#     DROP acts as if the packet did not exist.
#     REJECT responds with an error (then drop).
#     LOG creates a kernel log entry (in /var/log/syslog or /var/log/messesages) (then drop).
# The iptables interface:
#   sudo iptables
#     -L|--list -v|--verbose list current ip table entries (no --table shows filter table)
#     -F|--flush empty all ip table entries (no --table flushes filter table)
#     -A|--append creates a new rule
#     -j|--jump where to send the packet if the packet matches the rule
#     -i|--in-interface where packet must come for for a match
#     -o|--out-interface where packet must be going to for for a match
#     -m|--match state list,of,states allowed or a match
#     note: see man iptables for many other types of matching rules
#   Packets have a state:
#     NEW for the very first packet of a connection
#     ESTABLISHED for packets that are part of an existing connection
#     RELATED for packets related to another established connection (ftp)
#     INVALID for packets whose state is unknown or improper
#     UNTRACKED for packets specifically exempted from connection tracking
#     DNAT for packets whose destination address was changed by the table
#     SNAT for packets whose source address was changed by the table
#   Anything you block on the INPUT chain, you can’t access either.
#      --state RELATED,ESTABLISHED --jump ACCEPT declares "allow existing connections to continue"
# Save/restore iptables:
#   Once declared, iptables may be saved and restored to/from files of your choice.
#   iptables-save > iptables.rules # write current rules to configuration file
#   iptables-restore < iptables.rules # restore rules from configuration file
#   apt-get install iptables-persistent # package for automated iptables-save/restore

# Step 2: Turn on IP forwarding.

sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
sudo ifconfig $aEthernet $aIp_address netmask $aNetmask
# May also have to uncomment net.ipv4.ip_forward=1 in /etc/sysctl.conf
# Remove possible default route created by dhcpcd.
# Hide error if route does not exist.
sudo ip route del 0/0 dev $aEthernet &> /dev/null

# Step 3: Reconfigure and restart domain name masquerade.

sudo systemctl stop dnsmasq
cat > /tmp/custom-dnsmasq.conf <<-EOF
sudo rm -r /etc/dnsmasq.d/*
sudo cp /tmp/custom-dnsmasq.conf /etc/dnsmasq.d/custom-dnsmasq.conf
sudo systemctl start dnsmasq

# Show off what we did

echo "$(tput setaf 15)Table filter:$(tput sgr0)"
sudo iptables --list --verbose | sed 's/^/  /'
echo "$(tput setaf 15)Table nat:$(tput sgr0)"
sudo iptables --list --verbose --table nat | sed 's/^/  /'
echo "$(basename "$0"): @see $ sudo iptables -L -n -v # SHOW USAGE METERS ?"
# iptables-save # looking at the output is a good way to verify all the tables

Above is a program needing chmod +x which creates the NAT forwarding 'bridge' when executed. It will not automatically create the 'bridge' when you reboot.

Note: Packages like network-manager, wicd, connman, etc. all do their own thing. Such packages add configuration, GUI, and control layers that convolute everything. Uninstall all of them. This method uses only packages which actually perform a required task: dnsmasq, iptables, and wpasupplicant. The simpler you system, the simpler your solution.

Basic commands:

$ ip addr show # list every network interface and its current situation
$ sudo ifup INTERFACE # raise interface declared in /etc/network/interfaces
$ sudo ifdown INTERFACE # lower interface declared in /etc/network/interfaces
  • They can be bridged if the WiFi device can be run as an access point rather than an end node. Unfortunately many easy available devices do not come with the necessary firmware to run in this mode – roaima Dec 4 '20 at 21:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.