Working ok with a single xbnet, file structure and code encapsulation looking good, iptable updating ok, need to figure out issues with bridge network

This commit is contained in:
Emran Billah 2024-08-16 13:14:54 -03:00
parent eea579be93
commit 12d0ee8371
8 changed files with 221 additions and 27 deletions

15
.env Normal file → Executable file
View File

@ -1,11 +1,14 @@
# Configuration for xbnet0 # Configuration for xbnet0
XBEE0_PORT=/dev/ttyUSB0 XBEE0_PORT=/dev/ttyUSB0
XBEE0_BAUDRATE=/dev/ttyUSB0 XBEE0_BAUDRATE=230400
XBEE0_NET_SRC_IP=192.168.8.1 XBEE0_NET_SRC_IP=192.168.1.10 # Note: This requires the subnet 192.168.1... (to match with the default gateway, or use Masquerade if changing the subnet)
XBEE0_NET_DST_IP=192.168.8.2 XBEE0_NET_DST_IP=192.168.1.11 # Note: This requires the subnet 192.168.1... (to match with the default gateway, or use Masquerade if changing the subnet)
XBEE0_NET_IFACE_NAME=xbnet0
# Configuration for xbnet1 # Configuration for xbnet1
XBEE1_PORT=/dev/ttyUSB1 XBEE1_PORT=/dev/ttyUSB1
XBEE1_BAUDRATE=/dev/ttyUSB1 XBEE1_BAUDRATE=230400
XBEE1_NET_SRC_IP=192.168.8.2 XBEE1_NET_SRC_IP=192.168.1.11 # Note: This requires the subnet 192.168.1... (to match with the default gateway, or use Masquerade if changing the subnet)
XBEE1_NET_DST_IP=192.168.8.1 XBEE1_NET_DST_IP=192.168.1.10 # Note: This requires the subnet 192.168.1... (to match with the default gateway, or use Masquerade if changing the subnet)
XBEE1_NET_IFACE_NAME=xbnet1

View File

@ -1,11 +1,15 @@
# Use an official Rust image as the base # Use an official Rust image as the base
FROM rust:latest FROM rust:latest
# Install dependencies # Install necessary packages
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
libudev-dev \ libudev-dev \
iproute2 \ iproute2 \
iputils-ping \ iputils-ping \
net-tools \
bridge-utils \
iptables \
supervisor \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Clone the xbnet repository # Clone the xbnet repository
@ -13,14 +17,24 @@ RUN git clone https://github.com/jgoerzen/xbnet.git /usr/src/xbnet
# Build xbnet # Build xbnet
WORKDIR /usr/src/xbnet WORKDIR /usr/src/xbnet
RUN cargo build && cargo build --release RUN cargo build --release
# Copy the built binary to /usr/local/bin # Copy the built binary to /usr/local/bin (makes it accessible from anywhere in the OS)
RUN cp target/release/xbnet /usr/local/bin/xbnet RUN cp target/release/xbnet /usr/local/bin/xbnet
# Create and copy the entrypoint script to root location "/" # Copy the entrypoint script
COPY ./entrypoint.sh / COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"] # Copy the supervisor config file
CMD ["bash"] COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Copy the health check script from local ./scripts/ to container root /
COPY ./scripts/health_check.sh /health_check.sh
RUN chmod +x /health_check.sh
# Add the health check
HEALTHCHECK CMD /health_check.sh || exit 1
# Start supervisord as the main command
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

View File

@ -1,3 +1,7 @@
# TODO: This will not work with current configuration
# Use a bash script to either dynamicall generate this file or append to services
# based on how many xbnets you want to create
version: '3.8' version: '3.8'
services: services:

View File

@ -5,15 +5,15 @@ services:
build: . build: .
container_name: xbee_node container_name: xbee_node
privileged: true privileged: true
env_file: env_file: .env
- .env restart: always
devices: networks:
- "${XBEE0_PORT}:${XBEE0_PORT}" default:
command: > ipv4_address: ${XBEE0_NET_SRC_IP}
bash -c "
xbnet -d --serial-speed ${XBEE0_BAUDRATE} ${XBEE0_PORT} tun; networks:
ip addr add ${XBEE1_NET_SRC_IP}/24 dev xbnet0; default:
ip link set dev xbnet0 up; driver: bridge
ping -c 4 ${XBEE1_NET_DST_IP}; ipam:
sleep infinity config:
" - subnet: 192.168.1.0/24 # Note: the xbnet assigned IPs must be on this subnet (if Masquerade is not used)

View File

@ -1,4 +1,142 @@
#!/bin/bash #!/bin/bash
set -e # Source the get_connected_wifi_info.sh script
exec "$@" source ./scripts/get_connected_wifi_info.sh
# Check if the script is running with root privileges
check_root() {
if [ "$(id -u)" -ne 0 ]; then
echo "This script must be run as root. Exiting..."
exit 1
fi
}
# Clean up resources
# - Kill the background process used to create the xbnet interface
# - Cleanup any resources created or copied over. This includes:
# - Bridge interface
# - xbnet interface
cleanup() {
echo "Cleaning up resources..."
pkill -f "xbnet -d --serial-speed $XBEE0_BAUDRATE $XBEE0_PORT tap"
if ip link show br0 > /dev/null 2>&1; then
ip link set br0 down
brctl delbr br0
fi
if ip link show $XBEE0_NET_IFACE_NAME > /dev/null 2>&1; then
ip link set $XBEE0_NET_IFACE_NAME down
ip link delete $XBEE0_NET_IFACE_NAME
fi
}
# Function to check if the XBee device is connected
check_xbee_device() {
if [ -e "$XBEE0_PORT" ]; then
echo "XBee device found at $XBEE0_PORT. Proceeding with setup..."
return 0
else
echo "Error: No XBee device found at $XBEE0_PORT. Please connect the device."
return 1
fi
}
# Start the xbnet interface
# - Also check if the starting the xbnet interface was successful
# - And return appropriate status codes
start_xbnet_interface() {
echo "Starting XBee network interface..."
xbnet -d --serial-speed $XBEE0_BAUDRATE $XBEE0_PORT tap &
while [ ! -d "/sys/class/net/$XBEE0_NET_IFACE_NAME" ]; do
echo "Waiting for interface $XBEE0_NET_IFACE_NAME to be created..."
sleep 1
done
XBEE0_NET_IFACE_NAME=$(ls /sys/class/net | grep 'xbnet')
if [ -z "$XBEE0_NET_IFACE_NAME" ]; then
echo "Error: No XBee network interface found."
return 1
else
echo "XBee network interface $XBEE0_NET_IFACE_NAME created successfully."
return 0
fi
}
# Configure the network interface and bridge
# - Create interface with name specified by XBEE0_NET_IFACE_NAME in .env file
# - Create bridge interface (this bridge will be used to connect xbnet to host wifi)
# - Attach xbnet to bridge
# - Start the bridge interface
configure_network_and_bridge() {
ip addr add $XBEE0_NET_SRC_IP/24 dev $XBEE0_NET_IFACE_NAME
ip link set dev $XBEE0_NET_IFACE_NAME up
brctl addbr br0
brctl addif br0 $XBEE0_NET_IFACE_NAME
ip link set dev br0 up
}
# Monitor and bridge Wi-Fi
# - If a connected wifi interface is found
# - Add it to the bridge interface with xbnet
# - Else
# - keep looking for a newly established connection with a wifi interface
monitor_and_bridge_wifi() {
while true; do
HOST_WIFI_IFACE=$(get_connected_wifi_device)
if [ -n "$HOST_WIFI_IFACE" ]; then
echo "Wi-Fi interface found: $HOST_WIFI_IFACE. Bridging with $XBEE0_NET_IFACE_NAME..."
brctl addif br0 $HOST_WIFI_IFACE
iptables -t nat -A POSTROUTING -o $HOST_WIFI_IFACE -j MASQUERADE
iptables -A FORWARD -i br0 -o $HOST_WIFI_IFACE -j ACCEPT
iptables -A FORWARD -i $HOST_WIFI_IFACE -o br0 -j ACCEPT
echo "Bridge configured. Monitoring for changes..."
break
else
echo "No Wi-Fi interface found. Rechecking in 5 seconds..."
sleep 5
fi
done
}
# Function to monitor the XBee device and restart setup if disconnected
monitor_xbee_device() {
while [ -e "$XBEE0_PORT" ]; do
sleep 5
done
echo "XBee device at $XBEE0_PORT was removed. Cleaning up..."
cleanup
}
# Main function to set up the XBee network
setup_xbee_network() {
while true; do
check_xbee_device
if [ $? -ne 0 ]; then
sleep 5
continue
fi
start_xbnet_interface
if [ $? -ne 0 ]; then
cleanup
sleep 5
continue
fi
configure_network_and_bridge
monitor_and_bridge_wifi
monitor_xbee_device
done
}
# Run the setup only if the script is executed as root
check_root
setup_xbee_network

View File

@ -1,5 +1,15 @@
# get_connected_wifi_info.sh
#
# Usage: eg.
# source ./get_connected_wifi_info.sh
# wifi_device=$(get_connected_wifi_device)
# wifi_name=$(get_connected_wifi_name)
#
#!/bin/bash #!/bin/bash
# get_connected_wifi_device()
# - Returns wifi device id, eg. wlp0s20f3
get_connected_wifi_device() { get_connected_wifi_device() {
# Get the active Wi-Fi connections # Get the active Wi-Fi connections
connections=$(nmcli -t -f DEVICE,TYPE,STATE device | grep -E '^.*:wifi:connected$' | cut -d: -f1) connections=$(nmcli -t -f DEVICE,TYPE,STATE device | grep -E '^.*:wifi:connected$' | cut -d: -f1)
@ -13,6 +23,8 @@ get_connected_wifi_device() {
fi fi
} }
# get_connected_wifi_device()
# - Returns wifi device name, eg. spiri-field
get_connected_wifi_name() { get_connected_wifi_name() {
# Get the device name of the first connected Wi-Fi device # Get the device name of the first connected Wi-Fi device
device=$(get_connected_wifi_device) device=$(get_connected_wifi_device)

15
scripts/health_check.sh Normal file
View File

@ -0,0 +1,15 @@
#!/bin/bash
# Ensure the environment variables are loaded
source /etc/environment
# Perform the health check by pinging the xbnet interface
# - If the xbnet0 interface is successfully created, we should be able to ping the assigned IP
ping -c 1 "$XBEE0_NET_SRC_IP" > /dev/null 2>&1
# Return the appropriate status based on ping success
if [ $? -eq 0 ]; then
exit 0
else
exit 1
fi

8
supervisord.conf Normal file
View File

@ -0,0 +1,8 @@
[supervisord]
nodaemon=true
[program:xbnet]
command=/entrypoint.sh
autorestart=true
stderr_logfile=/var/log/xbnet.err.log
stdout_logfile=/var/log/xbnet.out.log