Skip to content

Instantly share code, notes, and snippets.

@AdamsGH
Created October 20, 2024 16:53
Show Gist options
  • Select an option

  • Save AdamsGH/d145a3249e3d5b708a9fe1796b865889 to your computer and use it in GitHub Desktop.

Select an option

Save AdamsGH/d145a3249e3d5b708a9fe1796b865889 to your computer and use it in GitHub Desktop.

Revisions

  1. AdamsGH created this gist Oct 20, 2024.
    220 changes: 220 additions & 0 deletions awg_config.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,220 @@
    #!/bin/bash

    # Colors
    RED='\033[0;31m'
    GREEN='\033[0;32m'
    YELLOW='\033[0;33m'
    BLUE='\033[0;34m'
    NC='\033[0m' # No Color

    # Function to print colored output
    print_color() {
    local color=$1
    shift
    echo -e "${color}$@${NC}"
    }

    # Function to display usage information
    show_usage() {
    print_color $BLUE "Usage: $0 <path_to_cfg_file> [interface_name] [peer_description] [zone] [-t|--test-route]"
    print_color $BLUE "Options:"
    print_color $BLUE " -t, --test-route Create a test route to 49.12.234.183"
    exit 1
    }

    # Function to get parameter from config file
    get_param() {
    sed -n "/$1/{s/^[^=]*=//; s/^[[:space:]]*//; s/[[:space:]]*$//; p}" "$cfg_file"
    }

    # Function to add or update network interface
    configure_interface() {
    if ! uci show network | grep -q "network.${interface_name}=interface"; then
    uci batch << EOI
    set network.${interface_name}=interface
    set network.${interface_name}.proto='amneziawg'
    set network.${interface_name}.private_key='$(get_param 'PrivateKey')'
    set network.${interface_name}.addresses='$(get_param 'Address')'
    set network.${interface_name}.force_link='1'
    set network.${interface_name}.delegate='0'
    set network.${interface_name}.dns='$(get_param 'DNS' | tr ',' ' ')'
    set network.${interface_name}.awg_jc='$(get_param 'Jc')'
    set network.${interface_name}.awg_jmin='$(get_param 'Jmin')'
    set network.${interface_name}.awg_jmax='$(get_param 'Jmax')'
    set network.${interface_name}.awg_h1='$(get_param 'H1')'
    set network.${interface_name}.awg_h2='$(get_param 'H2')'
    set network.${interface_name}.awg_h3='$(get_param 'H3')'
    set network.${interface_name}.awg_h4='$(get_param 'H4')'
    EOI
    print_color $GREEN "Interface ${interface_name} created."
    else
    print_color $YELLOW "Interface ${interface_name} already exists."
    fi
    }

    # Function to add or update peer
    configure_peer() {
    local peer_exists=false
    local peer_section=""

    # Check if peer already exists
    for peer in $(uci show network | grep "network.@amneziawg_${interface_name}\[" | cut -d. -f2 | cut -d= -f1); do
    if [ "$(uci get network.${peer}.description)" = "${peer_description}" ]; then
    peer_exists=true
    peer_section="${peer}"
    break
    fi
    done

    local allowed_ips=$(get_param 'AllowedIPs')
    IFS=',' read -ra ips <<< "$allowed_ips"

    if [ "$peer_exists" = false ]; then
    peer_section=$(uci add network amneziawg_${interface_name})
    uci batch << EOI
    set network.${peer_section}.description='${peer_description}'
    set network.${peer_section}.public_key='$(get_param 'PublicKey')'
    set network.${peer_section}.route_allowed_ips='0'
    set network.${peer_section}.persistent_keepalive='25'
    set network.${peer_section}.endpoint_host='$(get_param 'Endpoint' | cut -d':' -f1)'
    set network.${peer_section}.endpoint_port='$(get_param 'Endpoint' | cut -d':' -f2)'
    set network.${peer_section}.persistent_keepalive='60'
    EOI
    print_color $GREEN "Peer ${peer_description} added to interface ${interface_name}."
    else
    uci batch << EOI
    set network.${peer_section}.public_key='$(get_param 'PublicKey')'
    set network.${peer_section}.endpoint_host='$(get_param 'Endpoint' | cut -d':' -f1)'
    set network.${peer_section}.endpoint_port='$(get_param 'Endpoint' | cut -d':' -f2)'
    set network.${peer_section}.persistent_keepalive='60'
    delete network.${peer_section}.allowed_ips
    EOI
    print_color $YELLOW "Peer ${peer_description} updated in interface ${interface_name}."
    fi

    # Add allowed IPs
    for ip in "${ips[@]}"; do
    uci add_list network.${peer_section}.allowed_ips="${ip//[[:space:]]/}"
    done
    }

    # Function to configure firewall
    configure_firewall() {
    print_color $BLUE "Configuring firewall..."

    # Create or update the zone for the new interface
    zone_config=$(uci show firewall | grep "@zone\[.*\].name='${zone_name}'")
    if [ -z "$zone_config" ]; then
    # Create new zone
    new_zone=$(uci add firewall zone)
    uci batch << EOI
    set firewall.$new_zone.name='${zone_name}'
    set firewall.$new_zone.input='REJECT'
    set firewall.$new_zone.output='ACCEPT'
    set firewall.$new_zone.forward='REJECT'
    set firewall.$new_zone.masq='1'
    set firewall.$new_zone.mtu_fix='1'
    set firewall.$new_zone.network='${interface_name}'
    EOI
    print_color $GREEN "Created new firewall zone ${zone_name} for interface ${interface_name}."
    else
    # Update existing zone
    existing_zone=$(echo "$zone_config" | cut -d. -f2 | cut -d= -f1)
    uci set firewall.$existing_zone.network="${interface_name}"
    print_color $YELLOW "Updated existing firewall zone ${zone_name} with interface ${interface_name}."
    fi

    # Remove all existing forwarding rules for this zone
    existing_forwards=$(uci show firewall | grep "@forwarding\[[0-9]\+\]" | grep "\.dest='${zone_name}'")
    if [ -n "$existing_forwards" ]; then
    print_color $YELLOW "Removing existing forwarding rules for ${zone_name}..."
    echo "$existing_forwards" | while read -r line; do
    section=$(echo "$line" | cut -d. -f2 | cut -d= -f1)
    uci delete firewall.$section
    done
    fi

    # Add a single new forwarding rule
    new_forward=$(uci add firewall forwarding)
    uci set firewall.$new_forward.src='lan'
    uci set firewall.$new_forward.dest="${zone_name}"
    print_color $GREEN "Added new forwarding rule from LAN to ${zone_name}."

    print_color $GREEN "Firewall settings for ${zone_name} zone have been configured."
    }

    # Function to create test route
    create_test_route() {
    local address=$(get_param 'Address')
    local gateway=$(echo $address | awk -F'[./]' '{print $1"."$2"."$3".1"}')

    uci batch << EOI
    set network.test_route=route
    set network.test_route.interface='${interface_name}'
    set network.test_route.target='49.12.234.183/32'
    set network.test_route.gateway='${gateway}'
    EOI

    print_color $GREEN "Test route created:"
    print_color $BLUE " Target: 49.12.234.183/32"
    print_color $BLUE " Gateway: ${gateway}"
    print_color $BLUE " Interface: ${interface_name}"
    print_color $YELLOW "You can test the connection using: ${NC}curl 49.12.234.183"
    }

    # Main execution
    # Parse command line arguments
    CREATE_TEST_ROUTE=false
    while [[ $# -gt 0 ]]; do
    case $1 in
    -t|--test-route)
    CREATE_TEST_ROUTE=true
    shift
    ;;
    -h|--help)
    show_usage
    ;;
    *)
    if [ -z "$cfg_file" ]; then
    cfg_file="$1"
    elif [ -z "$interface_name" ]; then
    interface_name="$1"
    elif [ -z "$peer_description" ]; then
    peer_description="$1"
    elif [ -z "$zone_name" ]; then
    zone_name="$1"
    else
    print_color $RED "Unknown argument: $1"
    show_usage
    fi
    shift
    ;;
    esac
    done

    # Check for minimum required arguments
    [ -z "$cfg_file" ] && show_usage

    # Set default values if not provided
    interface_name="${interface_name:-AWG}"
    peer_description="${peer_description:-openwrt_router}"
    zone_name="${zone_name:-awg}"

    print_color $BLUE "Starting Amnezia WireGuard setup..."

    configure_interface
    configure_peer
    uci commit network

    configure_firewall
    uci commit firewall

    if [ "$CREATE_TEST_ROUTE" = true ]; then
    create_test_route
    uci commit network
    fi

    print_color $YELLOW "Restarting network..."
    /etc/init.d/network restart

    print_color $GREEN "Amnezia WireGuard setup completed."
    209 changes: 209 additions & 0 deletions awg_install.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,209 @@
    #!/bin/bash

    # Colors
    RED='\033[0;31m'
    GREEN='\033[0;32m'
    YELLOW='\033[0;33m'
    BLUE='\033[0;34m'
    NC='\033[0m' # No Color

    # Function to print colored output
    print_color() {
    local color=$1
    shift
    echo -e "${color}$@${NC}"
    }

    # Function to get release info
    get_release_info() {
    curl -s "https://api.github.com/repos/Slava-Shchipunov/awg-openwrt/releases/latest"
    }

    # Function to extract version from release info
    get_latest_version() {
    echo "$1" | grep -o '"tag_name": "v[^"]*"' | sed 's/"tag_name": "v//;s/"//'
    }

    # Function to get available files
    get_available_files() {
    echo "$1" | grep -o '"browser_download_url": "[^"]*\.ipk"' | sed 's/"browser_download_url": "//;s/"//'
    }

    # Function to get all architecture groups and their options
    get_all_arch_groups_and_options() {
    echo "$AVAILABLE_FILES" |
    sed -E 's/.*_v[^_]*_//; s/\.ipk$//' |
    sort -u |
    awk -F'_' '{
    group = $1;
    option = $2;
    for(i=3; i<=NF; i++) option = option "_" $i;
    if(option == "") option = "generic";
    if(group == "x86" && option ~ /^64/) {
    print group "|64";
    } else {
    print group "|" option;
    }
    }' |
    sort -t'|' -k1,1 -k2,2 |
    uniq
    }

    # Function to print groups and options
    print_groups_and_options() {
    local current_group=""
    while IFS='|' read -r group option; do
    if [ "$group" != "$current_group" ]; then
    if [ -n "$current_group" ]; then
    echo
    fi
    print_color $YELLOW "Group: $group"
    current_group="$group"
    fi
    if [ "$group" = "x86" ] && [ "$option" = "64" ]; then
    echo " 64"
    else
    echo " $option"
    fi
    done
    }

    # Function to get all architecture groups
    get_all_arch_groups() {
    echo "$AVAILABLE_FILES" | sed -E 's/.*_v[^_]*_([^_]+)(_.*\.ipk|\.ipk)/\1/' | sort -u
    }

    # Function to get available options for a group
    get_options() {
    local arch_group=$1
    echo "$AVAILABLE_FILES" | grep -E "_v${LATEST_VERSION}_${arch_group}" |
    sed -E "s/.*_v${LATEST_VERSION}_${arch_group}_//; s/\.ipk$//" |
    sort -u |
    sed '/^$/d'
    }

    # Function to install packages
    install_packages() {
    print_color $GREEN "Installing packages..."
    for package in awg/*.ipk; do
    if [ -f "$package" ]; then
    print_color $BLUE "Installing $package"
    opkg install "$package"
    if [ $? -eq 0 ]; then
    print_color $GREEN "Successfully installed $package"
    else
    print_color $RED "Failed to install $package"
    fi
    fi
    done
    }

    # Function to display usage
    usage() {
    print_color $BLUE "Usage: $0 <arch_group> [arch_option] [-i|--install] [-k|--keep]"
    print_color $BLUE "Example: $0 arm cortex-a9_neon_zynq_generic -i"
    print_color $BLUE "Or: $0 x86_64 --install --keep"
    print_color $BLUE "Use '$0 list' to see all available architecture groups and options"
    print_color $BLUE "Options:"
    print_color $BLUE " -i, --install Install packages after download"
    print_color $BLUE " -k, --keep Keep the download directory after installation"
    }

    # Main script starts here
    INSTALL=false
    KEEP=false
    ARCH_GROUP=""
    ARCH_OPTION=""

    # Parse command line arguments
    while [[ $# -gt 0 ]]; do
    case $1 in
    -i|--install)
    INSTALL=true
    shift
    ;;
    -k|--keep)
    KEEP=true
    shift
    ;;
    list|-h|--help)
    RELEASE_INFO=$(get_release_info)
    LATEST_VERSION=$(get_latest_version "$RELEASE_INFO")
    AVAILABLE_FILES=$(get_available_files "$RELEASE_INFO")
    print_color $GREEN "Available architecture groups and options:"
    get_all_arch_groups_and_options | print_groups_and_options
    exit 0
    ;;
    *)
    if [ -z "$ARCH_GROUP" ]; then
    ARCH_GROUP="$1"
    elif [ -z "$ARCH_OPTION" ]; then
    ARCH_OPTION="$1"
    else
    print_color $RED "Unknown argument: $1"
    usage
    exit 1
    fi
    shift
    ;;
    esac
    done

    if [ -z "$ARCH_GROUP" ]; then
    usage
    exit 1
    fi

    RELEASE_INFO=$(get_release_info)
    LATEST_VERSION=$(get_latest_version "$RELEASE_INFO")
    AVAILABLE_FILES=$(get_available_files "$RELEASE_INFO")

    if [ -z "$LATEST_VERSION" ]; then
    print_color $RED "Failed to extract version from release info."
    exit 1
    fi

    print_color $GREEN "Latest version: $LATEST_VERSION"

    if [ -z "$ARCH_OPTION" ]; then
    options=$(get_options $ARCH_GROUP)
    if [ -z "$options" ]; then
    FULL_ARCH="${ARCH_GROUP}"
    else
    print_color $YELLOW "Available options for $ARCH_GROUP:"
    echo "$options"
    exit 0
    fi
    else
    FULL_ARCH="${ARCH_GROUP}_${ARCH_OPTION}"
    fi

    # Download files
    rm -rf awg
    mkdir -p awg
    for FILE in amneziawg-tools kmod-amneziawg luci-app-amneziawg; do
    FULL_FILE=$(echo "$AVAILABLE_FILES" | grep "/${FILE}_v${LATEST_VERSION}_${FULL_ARCH}.ipk$")
    if [ -n "$FULL_FILE" ]; then
    OUTPUT_FILE="awg/${FILE}_v${LATEST_VERSION}_${FULL_ARCH}.ipk"
    if curl -s -L -o "$OUTPUT_FILE" "$FULL_FILE"; then
    print_color $GREEN "Downloaded: ${FILE}_v${LATEST_VERSION}_${FULL_ARCH}.ipk"
    else
    print_color $RED "Failed to download $FILE"
    fi
    else
    print_color $YELLOW "File $FILE for architecture $FULL_ARCH not found"
    fi
    done

    print_color $GREEN "Download completed."

    if [ "$INSTALL" = true ]; then
    install_packages
    if [ "$KEEP" = false ]; then
    print_color $YELLOW "Removing download directory..."
    rm -rf awg
    print_color $GREEN "Download directory removed."
    fi
    else
    print_color $YELLOW "Packages downloaded but not installed. Use -i or --install to install packages."
    fi