diff --git a/bridge/nat/wlan2eth.sh b/bridge/nat/run-bridge-nat.sh similarity index 100% rename from bridge/nat/wlan2eth.sh rename to bridge/nat/run-bridge-nat.sh diff --git a/bridge/nat/wlan2eth.service b/bridge/nat/wlan2eth.service index 64eaea4..ab7fd1a 100644 --- a/bridge/nat/wlan2eth.service +++ b/bridge/nat/wlan2eth.service @@ -6,7 +6,7 @@ After=basic.target network.target [Service] SyslogIdentifier=wlan2eth -ExecStart=/bin/bash /opt/wlan2eth/bridge/nat/wlan2eth.sh +ExecStart=/bin/bash /opt/wlan2eth/bridge/nat/run-bridge-nat.sh Restart=always RestartSec=2 diff --git a/bridge/proxyarp/README.md b/bridge/proxyarp/README.md index a616b0b..7f50db2 100644 --- a/bridge/proxyarp/README.md +++ b/bridge/proxyarp/README.md @@ -2,6 +2,6 @@ This bridge is a lot simpler than the NAT version. Just plug your client(s) into the bridge and it should just work. -Make sure to use a hub (NOT a switch) if you have more than one bridged client. A switch doesn't let the bridge see all the traffic from the clients. +I've heard people say that a hub (NOT a switch) is required when bridging more than one client (likely due to the fact that a switch doesn't let the bridge see all the traffic from the clients). But I don't think this matters. -Also, `parprouted` has a bug where it prints its error messages as raw Ethernet frames over the network. If something isn't working, open Wireshark and restart `parprouted`. Look for white "Ethernet II" frames. +Also, `parprouted` has a bug where it prints its log messages as raw Ethernet frames over the network. If something isn't working, open Wireshark and restart `parprouted`. Look for white "Ethernet II" frames. diff --git a/bridge/proxyarp/arp-install.sh b/bridge/proxyarp/arp-install.sh index 4abf370..0cd8807 100755 --- a/bridge/proxyarp/arp-install.sh +++ b/bridge/proxyarp/arp-install.sh @@ -157,38 +157,47 @@ grep '^enable-reflector=yes$' /etc/avahi/avahi-daemon.conf || { cat > /etc/systemd/system/parprouted.service < /etc/systemd/system/parprouted-monitor.service </dev/null 2>&1 && pwd) + SOURCE=$(readlink "$SOURCE") + [[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE +done +DIR=$(cd -P "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd) + +if [[ -f "$DIR/../../config/arp-config.sh" ]]; then + . "$DIR/../../config/arp-config.sh" +else + echo "$DIR/../../config/arp-config.sh missing!" + exit 1 +fi + +if [ "$(id -u)" -ne 0 ]; then + echo 'This script must be run as root.' >&2 + exit 1 +fi + +if [ ! -f "/sys/class/net/$ETH_IFACE/operstate" ]; then + echo "ERROR: $ETH_IFACE does not exist?" + echo "File does not exist: /sys/class/net/$ETH_IFACE/operstate" + exit 1 +fi + + +# ============================================================================== + +while true; do + if ethtool $ETH_IFACE | grep -q "Link detected: yes"; then + systemctl --quiet is-active parprouted || systemctl --quiet start parprouted + else + systemctl --quiet is-active parprouted && systemctl --quiet stop parprouted + fi + sleep 1 +done diff --git a/bridge/proxyarp/parprouted.sh b/bridge/proxyarp/parprouted.sh new file mode 100755 index 0000000..c0671fb --- /dev/null +++ b/bridge/proxyarp/parprouted.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +SOURCE=${BASH_SOURCE[0]} +while [ -L "$SOURCE" ]; do + DIR=$(cd -P "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd) + SOURCE=$(readlink "$SOURCE") + [[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE +done +DIR=$(cd -P "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd) + +if [[ -f "$DIR/../../config/arp-config.sh" ]]; then + . "$DIR/../../config/arp-config.sh" +else + echo "$DIR/../../config/arp-config.sh missing!" + exit 1 +fi + +if [ "$(id -u)" -ne 0 ]; then + echo 'This script must be run as root.' >&2 + exit 1 +fi + +if [ ! -f "/sys/class/net/$ETH_IFACE/operstate" ]; then + echo "ERROR: $ETH_IFACE does not exist?" + echo "File does not exist: /sys/class/net/$ETH_IFACE/operstate" + exit 1 +fi + +EXITING=0 + +function ctrl_c() { + # Reset the interfaces + if [ $EXITING -eq 0 ]; then # prevent running this multiple times + EXITING=1 + echo "Cleaning up..." + ip link set $WLAN_IFACE promisc off + ip link set dev $ETH_IFACE down + ip link set dev $ETH_IFACE up + ip addr del $(/sbin/ip -4 -br addr show $WLAN_IFACE | /bin/grep -Po "\\d+\\.\\d+\\.\\d+\\.\\d+")/32 dev $ETH_IFACE + exit + fi +} + +# ============================================================================== + +while ! ethtool $ETH_IFACE | grep -q "Link detected: yes"; do + echo "Waiting for wired interface $ETH_IFACE to come up..." + sleep 10s +done + + +# Clone our DCHP-allocated IP from wlan0 to eth0 so dhcp-helper will relay for the correct subnet +echo "Initializing..." +trap ctrl_c SIGINT +trap ctrl_c SIGTERM +ip addr add $(/sbin/ip -4 -br addr show $WLAN_IFACE | /bin/grep -Po "\\d+\\.\\d+\\.\\d+\\.\\d+")/32 dev $ETH_IFACE +ip link set $WLAN_IFACE promisc on + +while true; do + WLAN_IFACE_IP=$(ip -4 -br addr show $WLAN_IFACE | grep -Po "\\d+\\.\\d+\\.\\d+\\.\\d+") + if [ -n "${WLAN_IFACE_IP}" ]; then + break + fi + echo "Waiting for wireless interface $WLAN_IFACE to get an IP..." + sleep 10s +done + +parprouted -d $ETH_IFACE $WLAN_IFACE diff --git a/go/wlan2eth/arp/clients.go b/go/wlan2eth/arp/clients.go index 2c4f05e..1cd7d75 100644 --- a/go/wlan2eth/arp/clients.go +++ b/go/wlan2eth/arp/clients.go @@ -22,7 +22,7 @@ func (c ClientInfo) StringMAC() string { var bridgedClients = make(map[string]ClientInfo) var bridgedClientsLock sync.Mutex -func AddBridgedClient(ip net.IP, mac net.HardwareAddr, eth0MAC, wlan0MAC net.HardwareAddr, eth0 string) { +func AddBridgedClient(ip net.IP, mac, eth0MAC, wlan0MAC net.HardwareAddr, eth0 string) { log := logger.GetLogger() // Ignore the wlan0 MAC address @@ -30,18 +30,22 @@ func AddBridgedClient(ip net.IP, mac net.HardwareAddr, eth0MAC, wlan0MAC net.Har log.Debugf("Not adding client IP (wlan0): %s", ip) return } + // Ignore the eth0 MAC address if bytes.Equal(mac, eth0MAC) { log.Debugf("Not adding client IP (eth0): %s", ip) return } + // Sometimes this IP shows up if ip.String() == "0.0.0.0" { log.Debug("Not adding client IP: 0.0.0.0") return } + // Windows clients will self-assign an IP if isAPIPA(ip) { log.Debugf("Not adding client IP (APIPA): %s", ip) return } + // Exclude other wierdness if isExcluded(ip) { log.Debugf("Not adding client IP (excluded): %s", ip) return