arp proxy: add hotplug
This commit is contained in:
parent
9ad732c123
commit
a7396a23e4
|
@ -6,7 +6,7 @@ After=basic.target network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
SyslogIdentifier=wlan2eth
|
SyslogIdentifier=wlan2eth
|
||||||
ExecStart=/bin/bash /opt/wlan2eth/bridge/nat/wlan2eth.sh
|
ExecStart=/bin/bash /opt/wlan2eth/bridge/nat/run-bridge-nat.sh
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=2
|
RestartSec=2
|
||||||
|
|
||||||
|
|
|
@ -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.
|
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.
|
||||||
|
|
|
@ -157,38 +157,47 @@ grep '^enable-reflector=yes$' /etc/avahi/avahi-daemon.conf || {
|
||||||
|
|
||||||
cat > /etc/systemd/system/parprouted.service <<EOF
|
cat > /etc/systemd/system/parprouted.service <<EOF
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=proxy arp routing service
|
Description=Parprouted ARP Routing
|
||||||
Documentation=https://raspberrypi.stackexchange.com/q/88954/79866
|
Documentation=https://raspberrypi.stackexchange.com/q/88954/79866
|
||||||
#Requires=sys-subsystem-net-devices-$WLAN_IFACE.device dhcpcd.service
|
#Requires=sys-subsystem-net-devices-$WLAN_IFACE.device dhcpcd.service
|
||||||
#After=sys-subsystem-net-devices-$WLAN_IFACE.device dhcpcd.service
|
#After=sys-subsystem-net-devices-$WLAN_IFACE.device dhcpcd.service
|
||||||
After=network.target
|
After=network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=forking
|
Type=simple
|
||||||
# Restart until $WLAN_IFACE gained carrier
|
# Restart the service until $WLAN_IFACE gained carrier
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
TimeoutStartSec=30
|
TimeoutStartSec=30
|
||||||
# clone the dhcp-allocated IP to $ETH_IFACE so dhcp-helper will relay for the correct subnet
|
|
||||||
ExecStartPre=/bin/bash -c '/sbin/ip addr add \$(/sbin/ip -4 -br addr show $WLAN_IFACE | /bin/grep -Po "\\\d+\\\.\\\d+\\\.\\\d+\\\.\\\d+")/32 dev $ETH_IFACE'
|
ExecStart="$DIR/parprouted.sh"
|
||||||
ExecStartPre=/sbin/ip link set dev $ETH_IFACE down
|
RemainAfterExit=yes
|
||||||
ExecStartPre=/sbin/ip link set dev $ETH_IFACE up
|
|
||||||
ExecStartPre=/sbin/ip link set $WLAN_IFACE promisc on
|
|
||||||
ExecStart=-/usr/sbin/parprouted $ETH_IFACE $WLAN_IFACE
|
|
||||||
ExecStopPost=/sbin/ip link set $WLAN_IFACE promisc off
|
|
||||||
ExecStopPost=/sbin/ip link set dev $ETH_IFACE down
|
|
||||||
ExecStopPost=/sbin/ip link set dev $ETH_IFACE up
|
|
||||||
ExecStopPost=/bin/bash -c '/sbin/ip addr del \$(/sbin/ip -4 -br addr show $WLAN_IFACE | /bin/grep -Po "\\\d+\\\.\\\d+\\\.\\\d+\\\.\\\d+")/32 dev $ETH_IFACE'
|
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=wpa_supplicant.service
|
WantedBy=wpa_supplicant.service
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
cat > /etc/systemd/system/parprouted-monitor.service <<EOF
|
||||||
|
[Unit]
|
||||||
|
Description=Parprouted ARP Routing Hotplug
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart="$DIR/parprouted-monitor.sh"
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
ip link set dev $ETH_IFACE down
|
||||||
|
ip link set dev $ETH_IFACE up
|
||||||
|
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable --now parprouted dhcp-helper
|
systemctl enable --now parprouted dhcp-helper parprouted-monitor
|
||||||
systemctl restart parprouted dhcp-helper
|
systemctl restart parprouted dhcp-helper parprouted-monitor
|
||||||
|
|
||||||
systemctl status --no-pager dhcp-helper
|
systemctl status --no-pager dhcp-helper
|
||||||
systemctl status --no-pager parprouted
|
systemctl status --no-pager parprouted-monitor
|
||||||
|
systemctl status --no-pager parprouted.service
|
||||||
|
|
||||||
echo -e "\n==============\nDone!\nNow reboot!"
|
echo -e "\n==============\nDone!\nNow reboot!"
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
#!/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
|
||||||
|
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
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
|
|
@ -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
|
|
@ -22,7 +22,7 @@ func (c ClientInfo) StringMAC() string {
|
||||||
var bridgedClients = make(map[string]ClientInfo)
|
var bridgedClients = make(map[string]ClientInfo)
|
||||||
var bridgedClientsLock sync.Mutex
|
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()
|
log := logger.GetLogger()
|
||||||
|
|
||||||
// Ignore the wlan0 MAC address
|
// 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)
|
log.Debugf("Not adding client IP (wlan0): %s", ip)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Ignore the eth0 MAC address
|
||||||
if bytes.Equal(mac, eth0MAC) {
|
if bytes.Equal(mac, eth0MAC) {
|
||||||
log.Debugf("Not adding client IP (eth0): %s", ip)
|
log.Debugf("Not adding client IP (eth0): %s", ip)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Sometimes this IP shows up
|
||||||
if ip.String() == "0.0.0.0" {
|
if ip.String() == "0.0.0.0" {
|
||||||
log.Debug("Not adding client IP: 0.0.0.0")
|
log.Debug("Not adding client IP: 0.0.0.0")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Windows clients will self-assign an IP
|
||||||
if isAPIPA(ip) {
|
if isAPIPA(ip) {
|
||||||
log.Debugf("Not adding client IP (APIPA): %s", ip)
|
log.Debugf("Not adding client IP (APIPA): %s", ip)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Exclude other wierdness
|
||||||
if isExcluded(ip) {
|
if isExcluded(ip) {
|
||||||
log.Debugf("Not adding client IP (excluded): %s", ip)
|
log.Debugf("Not adding client IP (excluded): %s", ip)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue