diff --git a/documentation/docs/components/operators/snippets/quic-bridge-deployment-script-setup.mdx b/documentation/docs/components/operators/snippets/quic-bridge-deployment-script-setup.mdx index e13719945e..90a367d3c4 100644 --- a/documentation/docs/components/operators/snippets/quic-bridge-deployment-script-setup.mdx +++ b/documentation/docs/components/operators/snippets/quic-bridge-deployment-script-setup.mdx @@ -15,6 +15,7 @@ Operators can use [Nym Bridge Configuration Tool](https://github.com/nymtech/nym ###### 1. Download [`quic_bridge_deployment.sh`](https://github.com/nymtech/nym/blob/develop/scripts/nym-node-setup/quic_bridge_deployment.sh) script - SSH to your server +- **Run as root** - Download the script and make executable ```sh wget https://raw.githubusercontent.com/nymtech/nym/refs/heads/develop/scripts/nym-node-setup/quic_bridge_deployment.sh && \ @@ -26,7 +27,7 @@ chmod +x quic_bridge_deployment.sh - Optional: open `tmux` in case you will need to run another commands on the VPS - Run the script with a command `full_bridge_setup` ```sh -./nym-node-setup/quic_bridge_deployment.sh full_bridge_setup +./quic_bridge_deployment.sh full_bridge_setup ``` ###### 3. Follow the interactive prompts diff --git a/scripts/nym-node-setup/quic_bridge_deployment.sh b/scripts/nym-node-setup/quic_bridge_deployment.sh index fe3f1ec46f..0694fca81a 100644 --- a/scripts/nym-node-setup/quic_bridge_deployment.sh +++ b/scripts/nym-node-setup/quic_bridge_deployment.sh @@ -1,945 +1,540 @@ - #!/bin/bash +#!/usr/bin/env bash # Nym QUIC Bridge Deployment Helper Script -# This script provides network configuration and troubleshooting tools for Nym QUIC bridges - -network_device=$(ip route show default | awk '/default/ {print $5}') -wg_tunnel_interface="nymwg" - -BRIDGE_CONFIG_DIR="/opt/nym-bridge" -BRIDGE_KEYS_DIR="$BRIDGE_CONFIG_DIR/keys" -BRIDGE_CONFIG="$BRIDGE_CONFIG_DIR/bridges.toml" -CLIENT_PARAMS="$BRIDGE_CONFIG_DIR/client_bridge_params.json" -BRIDGE_BINARY="/usr/local/bin/nym-bridge" - - -if ! dpkg -s iptables-persistent >/dev/null 2>&1; then - echo "Installing iptables-persistent..." - sudo apt-get update - sudo apt-get install -y iptables-persistent -else - echo "iptables-persistent is already installed." -fi - -fetch_and_display_ipv6() { - ipv6_address=$(ip -6 addr show "$network_device" scope global | grep inet6 | awk '{print $2}') - if [[ -z "$ipv6_address" ]]; then - echo "No global IPv6 address found on $network_device." - else - echo "IPv6 address on $network_device: $ipv6_address" - fi +# Uses bridge-cfg to generate a correct bridges.toml and keys +# installs/maintains the nym-bridge service, and provides network helpers +# read about nym-bridges: https://github.com/nymtech/nym-bridges +# read about bridge-cfg: https://github.com/nymtech/nym-bridges/tree/main/bridge-cfg +# RUN AS ROOT + +set -euo pipefail + +# Colors +RED="\033[0;31m" +GREEN="\033[0;32m" +YELLOW="\033[0;33m" +CYAN="\033[0;36m" +BOLD="\033[1m" +RESET="\033[0m" + +# Logging +LOG_FILE="/var/log/nym-bridge-helper.log" +mkdir -p "$(dirname "$LOG_FILE")" +touch "$LOG_FILE" +chmod 640 "$LOG_FILE" +echo -e "${CYAN}Logs are being saved locally to:${RESET} $LOG_FILE" +echo -e "${CYAN}These logs never leave your machine.${RESET}" +echo "" | tee -a "$LOG_FILE" + +# safe logger +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE" } -fetch_wg_ipv6_address() { - ipv6_global_address=$(ip -6 addr show "$wg_tunnel_interface" scope global | grep inet6 | awk '{print $2}' | head -n 1) - - if [[ -z "$ipv6_global_address" ]]; then - echo "No globally routable IPv6 address found on $wg_tunnel_interface. Please configure IPv6 or check your network settings." - exit 1 - else - echo "Using IPv6 address: $ipv6_global_address" - fi -} - -adjust_ip_forwarding() { - ipv6_forwarding_setting="net.ipv6.conf.all.forwarding=1" - ipv4_forwarding_setting="net.ipv4.ip_forward=1" - - # Remove duplicate entries for these settings from the file - sudo sed -i "/^net.ipv6.conf.all.forwarding=/d" /etc/sysctl.conf - sudo sed -i "/^net.ipv4.ip_forward=/d" /etc/sysctl.conf - - echo "$ipv6_forwarding_setting" | sudo tee -a /etc/sysctl.conf - echo "$ipv4_forwarding_setting" | sudo tee -a /etc/sysctl.conf - - sudo sysctl -p /etc/sysctl.conf - - echo "IP forwarding enabled for IPv4 and IPv6." -} - -apply_bridge_iptables_rules() { - echo "Applying iptables rules for QUIC bridge ($wg_tunnel_interface)..." - sleep 1 - - # INPUT rules - allow incoming connections TO the bridge from WireGuard clients - # CRITICAL: This allows mobile clients to reach the bandwidth controller at 10.1.0.1:51830 - sudo iptables -I INPUT -i "$wg_tunnel_interface" -j ACCEPT - sudo ip6tables -I INPUT -i "$wg_tunnel_interface" -j ACCEPT - - # NAT rules - for outbound traffic masquerading - sudo iptables -t nat -A POSTROUTING -o "$network_device" -j MASQUERADE - sudo ip6tables -t nat -A POSTROUTING -o "$network_device" -j MASQUERADE - - # FORWARD rules - allow traffic through the bridge - sudo iptables -A FORWARD -i "$wg_tunnel_interface" -o "$network_device" -j ACCEPT - sudo iptables -A FORWARD -i "$network_device" -o "$wg_tunnel_interface" -m state --state RELATED,ESTABLISHED -j ACCEPT - sudo ip6tables -A FORWARD -i "$wg_tunnel_interface" -o "$network_device" -j ACCEPT - sudo ip6tables -A FORWARD -i "$network_device" -o "$wg_tunnel_interface" -m state --state RELATED,ESTABLISHED -j ACCEPT - - # Save rules - sudo iptables-save | sudo tee /etc/iptables/rules.v4 - sudo ip6tables-save | sudo tee /etc/iptables/rules.v6 - - echo "Iptables rules applied successfully for QUIC bridge (including INPUT rules for bandwidth controller)." -} - -check_bridge_iptables() { - echo "Inspecting iptables rules for QUIC bridge ($wg_tunnel_interface)..." - echo "---------------------------------------" - echo "IPv4 INPUT rules (for bandwidth controller):" - iptables -L INPUT -v -n | grep -E "$wg_tunnel_interface|Chain INPUT" | head -20 - echo "---------------------------------------" - echo "IPv4 FORWARD rules:" - iptables -L FORWARD -v -n | awk -v dev="$wg_tunnel_interface" '/^Chain FORWARD/ || $0 ~ dev || $0 ~ "ufw-reject-forward"' - echo "---------------------------------------" - echo "IPv6 INPUT rules (for bandwidth controller):" - ip6tables -L INPUT -v -n | grep -E "$wg_tunnel_interface|Chain INPUT" | head -20 - echo "---------------------------------------" - echo "IPv6 FORWARD rules:" - ip6tables -L FORWARD -v -n | awk -v dev="$wg_tunnel_interface" '/^Chain FORWARD/ || $0 ~ dev || $0 ~ "ufw6-reject-forward"' -} - -remove_duplicate_bridge_rules() { - local script_name=$(basename "$0") - - echo "Removing duplicate iptables rules for $wg_tunnel_interface..." - - iptables-save | grep "$wg_tunnel_interface" | while read -r line; do - sudo iptables -D ${line#-A } 2>/dev/null || echo "Failed to delete rule: $line" - done - - ip6tables-save | grep "$wg_tunnel_interface" | while read -r line; do - sudo ip6tables -D ${line#-A } 2>/dev/null || echo "Failed to delete rule: $line" - done - - echo "Duplicates removed for $wg_tunnel_interface." - echo "!!IMPORTANT!! You need to now reapply the iptables rules." - echo "Run: ./$script_name apply_bridge_iptables_rules" -} - -configure_dns_and_icmp() { - echo "Allowing ICMP (ping)..." - sudo iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT - sudo iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT - sudo ip6tables -A INPUT -p ipv6-icmp -j ACCEPT - sudo ip6tables -A OUTPUT -p ipv6-icmp -j ACCEPT - - echo "Allowing DNS over UDP (port 53)..." - sudo iptables -A INPUT -p udp --dport 53 -j ACCEPT - sudo ip6tables -A INPUT -p udp --dport 53 -j ACCEPT - - echo "Allowing DNS over TCP (port 53)..." - sudo iptables -A INPUT -p tcp --dport 53 -j ACCEPT - sudo ip6tables -A INPUT -p tcp --dport 53 -j ACCEPT - - echo "Saving iptables rules..." - sudo iptables-save | sudo tee /etc/iptables/rules.v4 - sudo ip6tables-save | sudo tee /etc/iptables/rules.v6 - - echo "DNS and ICMP configuration completed." -} - -check_ipv6_ipv4_forwarding() { - result_ipv4=$(cat /proc/sys/net/ipv4/ip_forward) - result_ipv6=$(cat /proc/sys/net/ipv6/conf/all/forwarding) - echo "IPv4 forwarding is $([ "$result_ipv4" == "1" ] && echo "enabled" || echo "not enabled")." - echo "IPv6 forwarding is $([ "$result_ipv6" == "1" ] && echo "enabled" || echo "not enabled")." +# simple redirection that keeps function scope intact +add_log_redirection() { + exec > >(tee -a "$LOG_FILE") 2>&1 } +add_log_redirection + +# Constants / Paths +REQUIRED_CMDS=(ip jq curl openssl wg dpkg) +BRIDGE_BIN="/usr/local/bin/nym-bridge" +BRIDGE_CFG_BIN="/usr/local/bin/bridge-cfg" + +NYM_ETC_DIR="/etc/nym" +NYM_ETC_KEYS_DIR="$NYM_ETC_DIR/keys" +NYM_ETC_BRIDGES="$NYM_ETC_DIR/bridges.toml" +NYM_ETC_CLIENT_PARAMS_DEFAULT="$NYM_ETC_DIR/client_bridge_params.json" +SERVICE_FILE="/etc/systemd/system/nym-bridge.service" + +NET_DEV="$(ip route show default 2>/dev/null | awk '/default/ {print $5}' || true)" +WG_IFACE="nymwg" + +# Root check +if [[ "$(id -u)" -ne 0 ]]; then + echo -e "\n${RED}This script must be run as root.${RESET}\n" + exit 1 +fi -check_ip_routing() { - echo "IPv4 routing table:" - ip route - echo "---------------------------------------" - echo "IPv6 routing table:" - ip -6 route +# UI helpers +hr() { echo -e "${YELLOW}----------------------------------------${RESET}"; } +title() { echo -e "\n${YELLOW}==========================================${RESET}\n${YELLOW} $1${RESET}\n${YELLOW}==========================================${RESET}\n"; } +ok() { echo -e "${GREEN}$1${RESET}"; } +warn() { echo -e "${YELLOW}$1${RESET}"; } +err() { echo -e "${RED}$1${RESET}"; } +info() { echo -e "${CYAN}$1${RESET}"; } +press_enter() { read -r -p "$1"; } + +# Helper: detect dpkg dependency failure for libc6>=2.34 +deb_depends_libc_too_old() { + # Grep dpkg -i output in log or run a dry call to dpkg -i with --unpack to observe code + # Simpler heuristic: check installed libc6 version + local v + v="$(dpkg-query -W -f='${Version}\n' libc6 2>/dev/null || true)" + # If no libc6, say "too old" to trigger source build + if [[ -z "$v" ]]; then return 0; fi + # Compare minimalistically: 2.34 vs current (2.31 typical on Debian 11) + dpkg --compare-versions "$v" ge "2.34" && return 1 || return 0 } -perform_pings() { - echo "Performing IPv4 ping to google.com..." - ping -4 -c 4 google.com - echo "---------------------------------------" - echo "Performing IPv6 ping to google.com..." - ping6 -c 4 google.com +# Helper: ensure rust toolchain (for local build fallback) +ensure_rustup() { + if ! command -v cargo >/dev/null 2>&1; then + info "Installing Rust toolchain (rustup)..." + apt-get update -y + DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates curl build-essential pkg-config libssl-dev git + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + export PATH="$HOME/.cargo/bin:$PATH" + else + export PATH="$HOME/.cargo/bin:$PATH" + fi } -test_bridge_connectivity() { - local green="\033[0;32m" - local reset="\033[0m" - local red="\033[0;31m" - local yellow="\033[0;33m" - - sleep 1 - echo - echo -e "${yellow}Testing QUIC bridge connectivity on $wg_tunnel_interface...${reset}" - echo -e "${yellow}If these tests succeed, it confirms the bridge can reach the outside world via IPv4 and IPv6.${reset}" - echo -e "${yellow}However, external clients may experience different connectivity to your bridge.${reset}" - - ipv4_address=$(ip addr show "$wg_tunnel_interface" | awk '/inet / {print $2}' | cut -d'/' -f1) - ipv6_address=$(ip addr show "$wg_tunnel_interface" | awk '/inet6 / && $2 !~ /^fe80/ {print $2}' | cut -d'/' -f1) - - if [[ -z "$ipv4_address" && -z "$ipv6_address" ]]; then - echo -e "${red}No IP address found on $wg_tunnel_interface. Unable to test connectivity.${reset}" - echo -e "${red}Please verify your bridge configuration and ensure the interface is up.${reset}" - return 1 - fi - - if [[ -n "$ipv4_address" ]]; then - echo - echo -e "------------------------------------" - echo -e "Detected IPv4 address: $ipv4_address" - echo -e "Testing IPv4 connectivity..." - echo - - if ping -4 -c 1 -I "$ipv4_address" google.com >/dev/null 2>&1; then - echo -e "${green}IPv4 connectivity is working. Fetching test data...${reset}" - joke=$(curl -s -H "Accept: application/json" --interface "$ipv4_address" https://icanhazdadjoke.com/ | jq -r .joke) - [[ -n "$joke" && "$joke" != "null" ]] && echo -e "${green}IPv4 test joke: $joke${reset}" || echo -e "${red}Failed to fetch test data via IPv4.${reset}" - else - echo -e "${red}IPv4 connectivity is not working for $wg_tunnel_interface. Verify your routing and NAT settings.${reset}" - fi - else - echo -e "${yellow}No IPv4 address found on $wg_tunnel_interface. Skipping IPv4 test.${reset}" - fi - - if [[ -n "$ipv6_address" ]]; then - echo - echo -e "------------------------------------" - echo -e "Detected IPv6 address: $ipv6_address" - echo -e "Testing IPv6 connectivity..." - echo - - if ping6 -c 1 -I "$ipv6_address" google.com >/dev/null 2>&1; then - echo -e "${green}IPv6 connectivity is working. Fetching test data...${reset}" - joke=$(curl -s -H "Accept: application/json" --interface "$ipv6_address" https://icanhazdadjoke.com/ | jq -r .joke) - [[ -n "$joke" && "$joke" != "null" ]] && echo -e "${green}IPv6 test joke: $joke${reset}" || echo -e "${red}Failed to fetch test data via IPv6.${reset}" - else - echo -e "${red}IPv6 connectivity is not working for $wg_tunnel_interface. Verify your routing and NAT settings.${reset}" - fi - else - echo -e "${yellow}No IPv6 address found on $wg_tunnel_interface. Skipping IPv6 test.${reset}" - fi - - echo -e "${green}Connectivity testing completed for $wg_tunnel_interface.${reset}" - echo -e "------------------------------------" - - sleep 2 - echo - echo - echo -e "${yellow}### Bridge Connectivity Testing Recommendations ###${reset}" - echo -e "${yellow}- Test UDP connectivity on port 51822 (used for Nym QUIC/WireGuard)${reset}" - echo -e "${yellow} From another machine: echo 'test message' | nc -u 51822${reset}" - echo -e "${yellow}- Test bandwidth controller access on port 51830:${reset}" - echo -e "${yellow} From inside the WireGuard tunnel: curl http://10.1.0.1:51830${reset}" - echo -e "${yellow}- If connectivity issues persist, check port forwarding and firewall rules${reset}" - echo +# Helper: clone and build from source at latest release tag +build_from_source_latest() { + local repo_url="https://github.com/nymtech/nym-bridges.git" + local workdir="/tmp/nym-bridges" + local tag + info "Determining latest release tag from GitHub..." + tag="$(curl -fsSL https://api.github.com/repos/nymtech/nym-bridges/releases/latest | jq -r .tag_name 2>/dev/null || true)" + if [[ -z "$tag" || "$tag" == "null" ]]; then + warn "Could not detect tag automatically. Falling back to 'main'." + tag="main" + fi + + info "Cloning $repo_url (tag/branch: $tag) into $workdir ..." + rm -rf "$workdir" + git clone --depth 1 --branch "$tag" "$repo_url" "$workdir" + (cd "$workdir" && cargo fetch) + + info "Building from source (release)..." + ( + cd "$workdir" + cargo build --release -p nym-bridge + cargo build --release -p bridge-cfg + ) + + # After build, binaries are typically in workspace target dir: + # /tmp/nym-bridges/target/release/nym-bridge + # /tmp/nym-bridges/target/release/bridge-cfg } -check_bridge_service_status() { - echo "Checking nym-bridge service status..." - systemctl status nym-bridge.service --no-pager - echo "---------------------------------------" - echo "Checking nym-node service status..." - systemctl status nym-node.service --no-pager +# Helper: robustly locate and install a built binary from /tmp/nym-bridges +install_built_binary() { + local name="$1" # e.g., bridge-cfg or nym-bridge + local preferred="/tmp/nym-bridges/target/release/$name" + + # Prefer the common workspace path first: + if [[ -x "$preferred" ]]; then + install -m 0755 "$preferred" "/usr/local/bin/$name" + ok "Installed $name from $preferred to /usr/local/bin/$name" + return 0 + fi + + # Try expected crate subpaths: + local alt1="/tmp/nym-bridges/$name/target/release/$name" + if [[ -x "$alt1" ]]; then + install -m 0755 "$alt1" "/usr/local/bin/$name" + ok "Installed $name from $alt1 to /usr/local/bin/$name" + return 0 + fi + + # Broader search within 8 levels: + local found + found="$(find /tmp/nym-bridges -maxdepth 8 -type f -name "$name" -perm -111 2>/dev/null | head -n1 || true)" + if [[ -n "$found" ]]; then + install -m 0755 "$found" "/usr/local/bin/$name" + ok "Installed $name from $found to /usr/local/bin/$name" + return 0 + fi + + err "Built $name not found under /tmp/nym-bridges after build." + return 1 } -show_bridge_logs() { - local lines=${1:-50} - echo "Showing last $lines lines of nym-bridge logs..." - journalctl -u nym-bridge.service -n "$lines" --no-pager +# Prerequisites +verify_bridge_prerequisites() { + title "Verifying Bridge Prerequisites" + local all_good=true + + for c in "${REQUIRED_CMDS[@]}"; do + if command -v "$c" >/dev/null 2>&1; then ok "✓ $c installed"; else err "$c missing"; all_good=false; fi + done + + echo "" + if ! dpkg -s iptables-persistent >/dev/null 2>&1; then + warn "iptables-persistent not installed" + info "Installing iptables-persistent..." + apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -y iptables-persistent + else + ok "✓ iptables-persistent installed" + fi + echo "" + + local v4=$(cat /proc/sys/net/ipv4/ip_forward 2>/dev/null || echo 0) + local v6=$(cat /proc/sys/net/ipv6/conf/all/forwarding 2>/dev/null || echo 0) + [[ "$v4" == "1" ]] && ok "✓ IPv4 forwarding enabled" || warn "IPv4 forwarding disabled" + [[ "$v6" == "1" ]] && ok "✓ IPv6 forwarding enabled" || warn "IPv6 forwarding disabled" + echo "" + + [[ "$all_good" == true ]] && ok "All prerequisites satisfied!" || warn "Some prerequisites missing." } -check_bridge_installation() { - local green="\033[0;32m" - local reset="\033[0m" - local red="\033[0;31m" - local yellow="\033[0;33m" - - echo -e "${yellow}=== Nym QUIC Bridge Installation Status ===${reset}" - echo "" - - # Check binary - if [[ -f "$BRIDGE_BINARY" ]]; then - echo -e "${green}✓ Bridge binary found: $BRIDGE_BINARY${reset}" - bridge_version=$($BRIDGE_BINARY --version 2>/dev/null | head -1 || echo "Unable to determine version") - echo " Version: $bridge_version" - else - echo -e "${red}✗ Bridge binary not found at $BRIDGE_BINARY${reset}" - fi - echo "" - - # Check configuration directory - if [[ -d "$BRIDGE_CONFIG_DIR" ]]; then - echo -e "${green}✓ Configuration directory exists: $BRIDGE_CONFIG_DIR${reset}" - else - echo -e "${red}✗ Configuration directory not found: $BRIDGE_CONFIG_DIR${reset}" - fi - echo "" - - # Check keys directory - if [[ -d "$BRIDGE_KEYS_DIR" ]]; then - echo -e "${green}✓ Keys directory exists: $BRIDGE_KEYS_DIR${reset}" - key_count=$(sudo bash -c "ls -1 \"$BRIDGE_KEYS_DIR\"/*.pem" 2>/dev/null | wc -l) - echo " Keys found: $key_count" - else - echo -e "${red}✗ Keys directory not found: $BRIDGE_KEYS_DIR${reset}" - fi - echo "" - - # Check configuration files - if [[ -f "$BRIDGE_CONFIG" ]]; then - echo -e "${green}✓ Bridge config found: $BRIDGE_CONFIG${reset}" - else - echo -e "${red}✗ Bridge config not found: $BRIDGE_CONFIG${reset}" - fi - - if [[ -f "$CLIENT_PARAMS" ]]; then - echo -e "${green}✓ Client params found: $CLIENT_PARAMS${reset}" - else - echo -e "${red}✗ Client params not found: $CLIENT_PARAMS${reset}" - fi - echo "" - - # Check services - echo -e "${yellow}Service Status:${reset}" - if systemctl is-active --quiet nym-bridge.service; then - echo -e "${green}✓ nym-bridge service is running${reset}" - else - echo -e "${red}✗ nym-bridge service is not running${reset}" - fi - - if systemctl is-active --quiet nym-node.service; then - echo -e "${green}✓ nym-node service is running${reset}" - else - echo -e "${red}✗ nym-node service is not running${reset}" - fi - echo "" +adjust_ip_forwarding() { + title "Adjusting IP Forwarding" + sed -i '/^net\.ipv4\.ip_forward=/d' /etc/sysctl.conf + sed -i '/^net\.ipv6\.conf\.all\.forwarding=/d' /etc/sysctl.conf + echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf + echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf + sysctl -p /etc/sysctl.conf + ok "IPv4/IPv6 forwarding enabled." } -show_bridge_config() { - echo "=== Bridge Configuration ===" - echo "" - - if [[ -f "$BRIDGE_CONFIG" ]]; then - echo "Bridge config ($BRIDGE_CONFIG):" - echo "---------------------------------------" - cat "$BRIDGE_CONFIG" - echo "" - else - echo "Bridge config not found at $BRIDGE_CONFIG" - fi - - if [[ -f "$CLIENT_PARAMS" ]]; then - echo "Client parameters ($CLIENT_PARAMS):" - echo "---------------------------------------" - cat "$CLIENT_PARAMS" - echo "" +# Install nym-bridge +install_bridge_binary() { + title "Installing nym-bridge Binary" + + info "Fetching latest nym-bridge .deb from GitHub..." + local deb_url + deb_url="$(curl -fsSL https://api.github.com/repos/nymtech/nym-bridges/releases/latest \ + | grep -Eo 'https://[^"]*/nym-bridge_[0-9.]+-1_amd64.deb' | head -n1 || true)" + + if [[ -z "$deb_url" ]]; then + warn "Falling back to known version (v0.1.2)" + deb_url="https://github.com/nymtech/nym-bridges/releases/download/bridge-binaries-v0.1.2/nym-bridge_0.1.2-1_amd64.deb" + fi + + info "Downloading from: $deb_url" + curl -fL -o /tmp/nym-bridge.deb "$deb_url" || true + + if [[ -s /tmp/nym-bridge.deb ]]; then + set +e + dpkg -i /tmp/nym-bridge.deb + local dpkg_rc=$? + set -e + if [[ $dpkg_rc -ne 0 ]]; then + warn "dpkg reported errors; checking for libc6>=2.34 requirement..." + if deb_depends_libc_too_old; then + warn "System libc6 appears older than 2.34. Building nym-bridge from source." + ensure_rustup + build_from_source_latest + install_built_binary "nym-bridge" + else + err "Failed to install nym-bridge .deb for non-libc reason; attempting source build." + ensure_rustup + build_from_source_latest + install_built_binary "nym-bridge" + fi else - echo "Client parameters not found at $CLIENT_PARAMS" + ok "nym-bridge installed via .deb." fi + else + warn "Download failed or empty. Building nym-bridge from source." + ensure_rustup + build_from_source_latest + install_built_binary "nym-bridge" + fi } -show_bridge_keys() { - local green="\033[0;32m" - local reset="\033[0m" - local red="\033[0;31m" - local yellow="\033[0;33m" - - echo -e "${yellow}=== Bridge Keys Information ===${reset}" - echo "" - - if [[ ! -d "$BRIDGE_KEYS_DIR" ]]; then - echo -e "${red}Keys directory not found: $BRIDGE_KEYS_DIR${reset}" - return 1 - fi - - echo "Keys directory: $BRIDGE_KEYS_DIR" - echo "---------------------------------------" - - # List all key files - if ls -1 "$BRIDGE_KEYS_DIR"/*.pem >/dev/null 2>&1; then - for key_file in "$BRIDGE_KEYS_DIR"/*.pem; do - key_name=$(basename "$key_file") - echo -e "${green}Key file: $key_name${reset}" - - # If it's a public key, show the content - if [[ "$key_name" == *"_bridge_identity.pem" ]]; then - echo " Type: ED25519 Bridge Identity (Private)" - echo " Path: $key_file" - - # Extract and show public key - if command -v openssl >/dev/null 2>&1; then - echo -e "${yellow} Public key (base64):${reset}" - openssl pkey -in "$key_file" -pubout 2>/dev/null | grep -v "\---" | base64 -d | tail -c 32 | base64 - fi - fi - echo "" - done +# Install bridge-cfg +install_bridge_cfg_tool() { + title "Installing bridge-cfg Tool" + + info "Attempting to fetch latest bridge-cfg from GitHub..." + local cfg_url + cfg_url="$(curl -fsSL https://api.github.com/repos/nymtech/nym-bridges/releases/latest \ + | grep -Eo 'https://[^"]*/bridge-cfg' | head -n1 || true)" + + if [[ -z "$cfg_url" ]]; then + warn "Falling back to v0.1.2" + cfg_url="https://github.com/nymtech/nym-bridges/releases/download/bridge-binaries-v0.1.2/bridge-cfg" + fi + + info "Downloading: $cfg_url" + if curl -fL -o "$BRIDGE_CFG_BIN" "$cfg_url"; then + chmod +x "$BRIDGE_CFG_BIN" + if "$BRIDGE_CFG_BIN" --help >/dev/null 2>&1; then + ok "bridge-cfg installed at $BRIDGE_CFG_BIN" + return 0 else - echo -e "${red}No key files found in $BRIDGE_KEYS_DIR${reset}" + warn "Prebuilt bridge-cfg is incompatible (likely GLIBC too old). Building locally..." fi + else + warn "Failed to download bridge-cfg; building locally..." + fi + + # Build from source and install robustly + ensure_rustup + build_from_source_latest + install_built_binary "bridge-cfg" } -show_bridge_info() { - local green="\033[0;32m" - local reset="\033[0m" - local yellow="\033[0;33m" +# Generate config via bridge-cfg (with backup) +run_bridge_cfg_generate() { + title "Generating Bridge Configuration with bridge-cfg" - echo -e "${yellow}=== Nym QUIC Bridge Information ===${reset}" - echo "" - - # Network interfaces - echo -e "${yellow}Network Configuration:${reset}" - echo "Primary network device: $network_device" - echo "WireGuard interface: $wg_tunnel_interface" - - # Show IP addresses - echo "" - echo "IPv4 addresses:" - ip -4 addr show | grep inet | awk '{print " " $2 " on " $NF}' - - echo "" - echo "IPv6 addresses:" - ip -6 addr show scope global | grep inet6 | awk '{print " " $2 " on " $NF}' - - echo "" - echo -e "${yellow}Bridge Paths:${reset}" - echo "Configuration: $BRIDGE_CONFIG_DIR" - echo "Keys: $BRIDGE_KEYS_DIR" - echo "Binary: $BRIDGE_BINARY" - - echo "" - echo -e "${yellow}Important Commands:${reset}" - echo " Check bridge status: systemctl status nym-bridge" - echo " Check nym-node status: systemctl status nym-node" - echo " View bridge logs: journalctl -u nym-bridge -f" - echo " View nym-node logs: journalctl -u nym-node -f" - echo "" -} - -verify_bridge_prerequisites() { - local green="\033[0;32m" - local reset="\033[0m" - local red="\033[0;31m" - local yellow="\033[0;33m" - - echo -e "${yellow}=== Verifying Bridge Prerequisites ===${reset}" - echo "" - - local all_good=true - - # Check IP forwarding - ipv4_forward=$(cat /proc/sys/net/ipv4/ip_forward) - ipv6_forward=$(cat /proc/sys/net/ipv6/conf/all/forwarding) + # Detect a likely nym-node configuration path + local HOME_DIR="${HOME:-/root}" + local NODE_CFG + NODE_CFG="$(find "$HOME_DIR/.nym/nym-nodes" -type f -name config.toml 2>/dev/null | head -n1 || true)" - if [[ "$ipv4_forward" == "1" ]]; then - echo -e "${green}✓ IPv4 forwarding enabled${reset}" - else - echo -e "${red}✗ IPv4 forwarding disabled${reset}" - echo " Fix: Run 'nym-bridge-helper adjust_ip_forwarding'" - all_good=false - fi - - if [[ "$ipv6_forward" == "1" ]]; then - echo -e "${green}✓ IPv6 forwarding enabled${reset}" - else - echo -e "${red}✗ IPv6 forwarding disabled${reset}" - echo " Fix: Run 'nym-bridge-helper adjust_ip_forwarding'" - all_good=false - fi - - # Check iptables-persistent - if dpkg -s iptables-persistent >/dev/null 2>&1; then - echo -e "${green}✓ iptables-persistent installed${reset}" - else - echo -e "${red}✗ iptables-persistent not installed${reset}" - echo " Fix: This script will auto-install on first run" - all_good=false - fi - - # Check required packages - for pkg in openssl jq curl wg; do - if command -v "$pkg" >/dev/null 2>&1; then - echo -e "${green}✓ $pkg installed${reset}" - else - echo -e "${red}✗ $pkg not installed${reset}" - if [[ "$pkg" == "wg" ]]; then - echo " Install: sudo apt install wireguard-tools" - fi - all_good=false - fi - done + if [[ -z "$NODE_CFG" ]]; then + NODE_CFG="$HOME_DIR/.nym/nym-nodes/default-nym-node/config/config.toml" + fi - echo "" - if [[ "$all_good" == true ]]; then - echo -e "${green}All prerequisites satisfied!${reset}" - else - echo -e "${yellow}Some prerequisites need attention. See above for fixes.${reset}" - fi - echo "" -} + echo -n "Path to your nym-node config.toml [default: $NODE_CFG]: " + read -r input + [[ -n "$input" ]] && NODE_CFG="$input" -generate_bridge_keys() { - local green="\033[0;32m" - local reset="\033[0m" - local red="\033[0;31m" - local yellow="\033[0;33m" - - echo -e "${yellow}=== Generating Bridge Keys ===${reset}" - echo "" - - # Create directories - sudo mkdir -p "$BRIDGE_CONFIG_DIR" - sudo mkdir -p "$BRIDGE_KEYS_DIR" - sudo chmod 700 "$BRIDGE_KEYS_DIR" - - # Generate ED25519 private key - local key_file="$BRIDGE_KEYS_DIR/ed25519_bridge_identity.pem" - - if sudo test -f "$key_file"; then - echo -e "${yellow}Warning: Key file already exists at $key_file${reset}" - read -p "Overwrite existing key? (yes/no): " confirm - if [[ "$confirm" != "yes" ]]; then - echo "Aborted. Keeping existing key." - return 1 - fi - fi - - echo "Generating ED25519 key..." - sudo openssl genpkey -algorithm ED25519 -out "$key_file" - sudo chmod 600 "$key_file" - - echo -e "${green}✓ Bridge key generated at $key_file${reset}" - - # Extract and display public key - echo "" - echo "Extracting public key..." - pubkey=$(sudo openssl pkey -in "$key_file" -pubout 2>/dev/null | grep -v "\---" | base64 -d | tail -c 32 | base64) - echo -e "${green}Public key (base64): $pubkey${reset}" - - echo "" - echo -e "${yellow}Next steps:${reset}" - echo "1. Run 'nym-bridge-helper create_client_params' to generate client parameters" - echo "2. Run 'nym-bridge-helper create_bridge_config' to create bridge configuration" -} - -create_client_params() { - local green="\033[0;32m" - local reset="\033[0m" - local red="\033[0;31m" - local yellow="\033[0;33m" - - echo -e "${yellow}=== Creating Client Bridge Parameters ===${reset}" - echo "" - - # Check if key exists - local key_file="$BRIDGE_KEYS_DIR/ed25519_bridge_identity.pem" - if ! sudo test -f "$key_file"; then - echo -e "${red}Error: Bridge key not found at $key_file${reset}" - echo "Run 'nym-bridge-helper generate_bridge_keys' first" - return 1 - fi - - # Get forward address - read -p "Enter forward address (e.g., :51822, can be found by running 'curl -4 https://ifconfig.co/ip'): " forward_addr - if [[ -z "$forward_addr" ]]; then - echo -e "${red}Error: Forward address is required${reset}" - return 1 - fi - - # Extract public key - echo "Extracting public key..." - pubkey=$(sudo openssl pkey -in "$key_file" -pubout 2>/dev/null | grep -v "\---" | base64 -d | tail -c 32 | base64) - - # Create client params JSON - echo "Creating client parameters file..." - sudo tee "$CLIENT_PARAMS" > /dev/null < /dev/null < /dev/null - fi - - sudo tee -a "$BRIDGE_CONFIG" > /dev/null </dev/null || true -# Additional settings -bandwidth_controller_port = 51830 -EOF + ok "bridge-cfg completed. bridges.toml generated at $NYM_ETC_BRIDGES" + echo "" + hr + head -n 50 "$NYM_ETC_BRIDGES" + hr - sudo chmod 644 "$BRIDGE_CONFIG" - - echo -e "${green}✓ Bridge configuration created at $BRIDGE_CONFIG${reset}" - echo "" - echo "Configuration preview:" - cat "$BRIDGE_CONFIG" + export LAST_BACKUP_FILE="$BACKUP_FILE" } +# Systemd service create_bridge_service() { - local green="\033[0;32m" - local reset="\033[0m" - local red="\033[0;31m" - local yellow="\033[0;33m" + title "Creating nym-bridge systemd Service" - echo -e "${yellow}=== Creating nym-bridge systemd Service ===${reset}" - echo "" + # Respect a service provided by .deb postinst if present + if systemctl list-unit-files | grep -q '^nym-bridge\.service'; then + warn "Detected existing nym-bridge service (likely from .deb). Not overwriting." + systemctl daemon-reload || true + systemctl enable nym-bridge >/dev/null || true + systemctl restart nym-bridge || true + ok "nym-bridge service managed by package; restarted." + return 0 + fi - # Check if bridge binary exists - if [[ ! -f "$BRIDGE_BINARY" ]]; then - echo -e "${red}Error: Bridge binary not found at $BRIDGE_BINARY${reset}" - echo "Please install the nym-bridge binary first" - return 1 - fi + if [[ ! -x "$BRIDGE_BIN" ]]; then err "Missing $BRIDGE_BIN"; exit 1; fi + if [[ ! -f "$NYM_ETC_BRIDGES" ]]; then err "Missing $NYM_ETC_BRIDGES"; exit 1; fi - # Check if config exists - if [[ ! -f "$BRIDGE_CONFIG" ]]; then - echo -e "${red}Error: Bridge config not found at $BRIDGE_CONFIG${reset}" - echo "Run 'nym-bridge-helper create_bridge_config' first" - return 1 - fi + mkdir -p /etc/systemd/system - # Create systemd service file - local service_file="/etc/systemd/system/nym-bridge.service" - - echo "Creating systemd service file..." - sudo tee "$service_file" > /dev/null < "$SERVICE_FILE" </dev/null || true + systemctl restart nym-bridge || true + ok "nym-bridge service deployed." } -install_bridge_binary() { - local green="\033[0;32m" - local reset="\033[0m" - local red="\033[0;31m" - local yellow="\033[0;33m" - - local deb_arch="amd64" - local sys_arch=$(dpkg --print-architecture) - - if [[ "$deb_arch" != "$sys_arch" ]]; then - echo -e "${red}Error: aborting .deb package installation as this system's arch is not amd64.${reset}" - echo " Refer to https://github.com/nymtech/nym-bridges for build instructions." - exit 1 - fi - - echo -e "${yellow}=== Installing nym-bridge Binary ===${reset}" - echo "" - - echo "Retrieving URL to latest release..." - local binary_url=$( - curl -s "https://api.github.com/repos/nymtech/nym-bridges/releases/latest" | - grep "browser_download_url.*amd64.deb" | - grep -o 'https://[^"]*' - ) +# IPTABLES & helpers +apply_bridge_iptables_rules() { + title "Applying iptables rules" + iptables -I INPUT -i "$WG_IFACE" -j ACCEPT || true + ip6tables -I INPUT -i "$WG_IFACE" -j ACCEPT || true + iptables -t nat -A POSTROUTING -o "$NET_DEV" -j MASQUERADE || true + ip6tables -t nat -A POSTROUTING -o "$NET_DEV" -j MASQUERADE || true + iptables-save > /etc/iptables/rules.v4 + ip6tables-save > /etc/iptables/rules.v6 + ok "iptables rules applied." +} - echo "Downloading $binary_url ..." - if curl -L -o "/tmp/$(basename "$binary_url")" "$binary_url"; then - sudo dpkg -i "/tmp/$(basename "$binary_url")" - else - echo -e "${red}✗ Failed to download bridge binary${reset}" - return 1 - fi +configure_dns_and_icmp() { + title "Allow ICMP and DNS" + iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT || true + ip6tables -A INPUT -p ipv6-icmp -j ACCEPT || true + ok "ICMP and DNS rules applied." } +# Full interactive setup (safe exit + backup notice) full_bridge_setup() { - local green="\033[0;32m" - local reset="\033[0m" - local yellow="\033[0;33m" - - echo -e "${yellow}========================================${reset}" - echo -e "${yellow} Nym QUIC Bridge - Full Setup${reset}" - echo -e "${yellow}========================================${reset}" - echo "" - - echo "This will guide you through complete bridge setup" - echo "" - - # Step 1: Prerequisites - echo "Step 1/7: Checking prerequisites..." - verify_bridge_prerequisites - read -p "Press Enter to continue..." - - # Step 2: Install binary - echo "" - echo "Step 2/7: Installing bridge binary..." - install_bridge_binary - read -p "Press Enter to continue..." - - # Step 3: Generate keys - echo "" - echo "Step 3/7: Generating bridge keys..." - generate_bridge_keys - read -p "Press Enter to continue..." - - # Step 4: Create client params - echo "" - echo "Step 4/7: Creating client parameters..." - create_client_params - read -p "Press Enter to continue..." - - # Step 5: Create bridge config - echo "" - echo "Step 5/7: Creating bridge configuration..." - create_bridge_config - read -p "Press Enter to continue..." - - # Step 6: Create service - echo "" - echo "Step 6/7: Creating systemd service..." - create_bridge_service - read -p "Press Enter to continue..." + title "Nym QUIC Bridge - Full Setup" - # Step 7: Network setup - echo "" - echo "Step 7/7: Configuring network..." - adjust_ip_forwarding - apply_bridge_iptables_rules - configure_dns_and_icmp + echo -e "This will guide you through complete bridge setup.\n" - echo "" - echo -e "${green}========================================${reset}" - echo -e "${green} Bridge Setup Complete!${reset}" - echo -e "${green}========================================${reset}" - echo "" - echo "To start the bridge:" - echo " sudo systemctl enable nym-bridge" - echo " sudo systemctl start nym-bridge" - echo "" - echo "To check status:" - echo " nym-bridge-helper check_bridge_service_status" + for fn in verify_bridge_prerequisites install_bridge_binary install_bridge_cfg_tool \ + run_bridge_cfg_generate create_bridge_service adjust_ip_forwarding \ + apply_bridge_iptables_rules configure_dns_and_icmp; do + if ! declare -f "$fn" >/dev/null; then + err "Internal error: required function '$fn' is missing." + exit 1 + fi + done + + echo "Step 1/6: Checking prerequisites..." + verify_bridge_prerequisites + press_enter "Press Enter to continue..." + + echo "" + echo "Step 2/6: Installing bridge binary..." + install_bridge_binary + press_enter "Press Enter to continue..." + + echo "" + echo "Step 3/6: Installing bridge-cfg tool..." + install_bridge_cfg_tool + press_enter "Press Enter to continue..." + + echo "" + echo "Step 4/6: Generating configuration with bridge-cfg..." + run_bridge_cfg_generate + press_enter "Press Enter to continue..." + + echo "" + echo "Step 5/6: Creating and starting systemd service..." + create_bridge_service + press_enter "Press Enter to continue..." + + echo "" + echo "Step 6/6: Configuring network rules (optional but recommended)..." + adjust_ip_forwarding + apply_bridge_iptables_rules + configure_dns_and_icmp + + title "Bridge Setup Complete!" + + if systemctl --quiet is-active nym-bridge; then + ok "nym-bridge service is running." + else + warn "nym-bridge failed to start. Check logs with:" + echo " journalctl -u nym-bridge -n 50 --no-pager" + fi + + echo "" + ok "Setup completed successfully." + + echo "" + echo -e "${YELLOW}------------------------------------------${RESET}" + echo -e "All done! You can safely close this session." + echo -e "${YELLOW}------------------------------------------${RESET}" + echo "" + echo "Logs saved locally at: $LOG_FILE" + echo "Operation 'full_bridge_setup' completed." + echo "" + + hr + echo -e "${CYAN}Next steps and verification:${RESET}" + hr + echo "" + echo -e "${YELLOW}To verify that the Nym Bridge service is active:${RESET}" + echo " systemctl status nym-bridge --no-pager" + echo " journalctl -u nym-bridge -n 50 --no-pager" + echo "" + echo -e "${YELLOW}To view live logs in real time:${RESET}" + echo " journalctl -u nym-bridge -f" + echo "" + echo -e "${YELLOW}To restart or reload the bridge service later:${RESET}" + echo " systemctl restart nym-bridge" + echo "" + echo -e "${YELLOW}To ensure your nym-node is properly aligned with the bridge:${RESET}" + echo " systemctl restart nym-node" + echo "" + echo -e "${YELLOW}Optional network diagnostics:${RESET}" + echo " ip addr show nymwg" + echo " ping -c 3 google.com" + echo " ping6 -c 3 google.com" + echo "" + + if [[ -n "${LAST_BACKUP_FILE:-}" ]]; then + echo "" + echo -e "${GREEN}Backup of your nym-node config created at:${RESET} ${LAST_BACKUP_FILE}" + fi + + hr + echo -e "${GREEN}Bridge and node setup complete. Both services are ready to use.${RESET}" + hr + echo "" } -case "$1" in -fetch_and_display_ipv6) - fetch_and_display_ipv6 - ;; -fetch_wg_ipv6_address) - fetch_wg_ipv6_address - ;; -apply_bridge_iptables_rules) - apply_bridge_iptables_rules - ;; -check_bridge_iptables) - check_bridge_iptables - ;; -remove_duplicate_bridge_rules) - remove_duplicate_bridge_rules - ;; -configure_dns_and_icmp) - configure_dns_and_icmp - ;; -adjust_ip_forwarding) - adjust_ip_forwarding - ;; -check_ipv6_ipv4_forwarding) - check_ipv6_ipv4_forwarding - ;; -check_ip_routing) - check_ip_routing - ;; -perform_pings) - perform_pings - ;; -test_bridge_connectivity) - test_bridge_connectivity - ;; -check_bridge_service_status) - check_bridge_service_status - ;; -show_bridge_logs) - show_bridge_logs "$2" - ;; -check_bridge_installation) - check_bridge_installation - ;; -show_bridge_config) - show_bridge_config - ;; -show_bridge_keys) - show_bridge_keys - ;; -show_bridge_info) - show_bridge_info - ;; -verify_bridge_prerequisites) - verify_bridge_prerequisites - ;; -generate_bridge_keys) - generate_bridge_keys - ;; -create_client_params) - create_client_params - ;; -create_bridge_config) - create_bridge_config - ;; -create_bridge_service) - create_bridge_service - ;; -install_bridge_binary) - install_bridge_binary - ;; -full_bridge_setup) - full_bridge_setup - ;; -*) - echo "Usage: $0 [command] [options]" - echo "" - echo "Nym QUIC Bridge Deployment Helper Script" - echo "" - echo "Bridge Installation & Configuration:" - echo " check_bridge_installation - Check bridge installation status" - echo " show_bridge_config - Display bridge configuration files" - echo " show_bridge_keys - Display bridge key information" - echo " show_bridge_info - Show comprehensive bridge information" - echo " verify_bridge_prerequisites - Verify all prerequisites are met" - echo "" - echo "Bridge Setup Commands:" - echo " install_bridge_binary - Download and install nym-bridge binary" - echo " generate_bridge_keys - Generate ED25519 bridge identity keys" - echo " create_client_params - Create client_bridge_params.json" - echo " create_bridge_config - Create bridges.toml configuration" - echo " create_bridge_service - Create systemd service file" - echo " full_bridge_setup - Interactive full bridge setup wizard" - echo "" - echo "Network Configuration Commands:" - echo " adjust_ip_forwarding - Enable IPv4 and IPv6 forwarding" - echo " apply_bridge_iptables_rules - Apply iptables rules for QUIC bridge (nymwg)" - echo " configure_dns_and_icmp - Allow ICMP ping tests and configure DNS" - echo " remove_duplicate_bridge_rules - Remove duplicate iptables rules for nymwg" - echo "" - echo "Network Inspection Commands:" - echo " fetch_and_display_ipv6 - Show IPv6 on default network device" - echo " fetch_wg_ipv6_address - Fetch IPv6 for nymwg interface" - echo " check_bridge_iptables - Check iptables rules for nymwg" - echo " check_ipv6_ipv4_forwarding - Check IPv4 and IPv6 forwarding status" - echo " check_ip_routing - Display IP routing tables" - echo "" - echo "Testing Commands:" - echo " perform_pings - Test IPv4 and IPv6 connectivity" - echo " test_bridge_connectivity - Comprehensive bridge connectivity test" - echo "" - echo "Service Management Commands:" - echo " check_bridge_service_status - Check nym-bridge and nym-node service status" - echo " show_bridge_logs [lines] - Show recent nym-bridge logs (default: 50 lines)" - echo "" - echo "Quick Start:" - echo " 1. Run 'verify_bridge_prerequisites' to check prerequisites" - echo " 2. Run 'check_bridge_installation' to verify installation" - echo " 3. Run 'test_bridge_connectivity' to test connectivity" +graceful_exit() { + local exit_code=$? + echo "" + echo -e "${YELLOW}------------------------------------------${RESET}" + if [[ $exit_code -eq 0 ]]; then + echo -e "${GREEN}Setup completed successfully. Exiting cleanly.${RESET}" + else + echo -e "${RED}Script exited with errors (code: $exit_code).${RESET}" + echo "Check the log at: $LOG_FILE" + fi + echo -e "${YELLOW}------------------------------------------${RESET}" + echo "" + exec >&- 2>&- + exit $exit_code +} +trap graceful_exit EXIT + +# Command menu +case "${1:-}" in + full_bridge_setup) full_bridge_setup ;; + install_bridge_binary) install_bridge_binary ;; + install_bridge_cfg_tool) install_bridge_cfg_tool ;; + run_bridge_cfg_generate) run_bridge_cfg_generate ;; + create_bridge_service) create_bridge_service ;; + adjust_ip_forwarding) adjust_ip_forwarding ;; + apply_bridge_iptables_rules) apply_bridge_iptables_rules ;; + configure_dns_and_icmp) configure_dns_and_icmp ;; + *) + echo -e "\nUsage: $0 [command]\n" + echo "Commands:" + echo " full_bridge_setup - Run full setup" + echo " install_bridge_binary - Install nym-bridge (.deb; falls back to source build if libc too old)" + echo " install_bridge_cfg_tool - Install bridge-cfg (prebuilt; falls back to source build if libc too old)" + echo " run_bridge_cfg_generate - Generate bridges.toml" + echo " create_bridge_service - Setup systemd service (respects .deb-provided service)" + echo " adjust_ip_forwarding - Enable forwarding" + echo " apply_bridge_iptables_rules - NAT rules" + echo " configure_dns_and_icmp - Allow ICMP/DNS" echo "" exit 1 ;; esac -echo "Operation '$1' completed successfully." - +echo "Operation '${1:-help}' completed."