Created
April 10, 2025 21:42
-
-
Save pedro0311/548622f1700460b2de8814942e9acbfa to your computer and use it in GitHub Desktop.
This script will create the configuration for your wireguard site-to-site full mesh VPN
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| # wg.sh ver 1.22 - rs232 - 03/23 | |
| # DO NOT EDIT THIS FILE! | |
| # All the config is placed in the wg0.conf and you can produce this automatically via "wg.sh makeconf" | |
| export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/home/root | |
| PID=$$ | |
| black="\033[0;40m" | |
| grey="\033[0;5;238m" | |
| green="\033[48;2;32m" | |
| alias logw='logger -p WARN -t wg-sh[$PID]' | |
| DIR=$(dirname "$0") | |
| cd $DIR; DIR=$(pwd) | |
| int=wg0 | |
| checkmin=$(grep 'checkmin=' ${DIR}/${int}.conf | cut -d= -f2) | |
| port=$(grep 'ListenPort' ${DIR}/${int}.conf | awk '{print $3}') | |
| vnet=$(grep 'vnet=' ${DIR}/${int}.conf | cut -d= -f2) | |
| rnet=$(grep -Ev '^($|#|\[)' ${DIR}/${int}.conf | grep -Eo '(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/..' | grep -v .*/32$) | |
| [ $# -gt 0 ] && { | |
| [ $1 == "stop" ] && { | |
| iptables -t mangle -nvL PREROUTING | grep -q '.*MARK.*all.*wg0.*0x1/0x7' && iptables -t mangle -D PREROUTING -i $int -j MARK --set-mark 0x01/0x7 | |
| iptables -nvL INPUT | grep -q ".*ACCEPT.*udp.dpt.${port}$" && iptables -D INPUT -p udp --dport $port -j ACCEPT | |
| iptables -nvL INPUT | grep -q ".*ACCEPT.*all.*$int" && iptables -D INPUT -i $int -j ACCEPT | |
| iptables -nvL FORWARD | grep -q ".*ACCEPT.*all.*$int" && iptables -D FORWARD -i $int -j ACCEPT | |
| ip route | grep -Eo ".*dev.$int.*" | while read line; do ip route del $(echo $line | awk '{print $1}'); done | |
| ifconfig $int down 2>/dev/null | |
| ip link del dev $int 2>/dev/null | |
| rmmod wireguard 2>/dev/null | |
| cru l | grep -q '#wireguard-check#' && cru d wireguard-check | |
| echo stopped. | |
| exit | |
| } | |
| [ $1 == "check" -a $(wg | wc -l) -gt 3 ] && { | |
| echo $rnet | tr " " "\n" | while read line; do | |
| rsite=$(echo $line | cut -d. -f3 | grep -Eo '^[0-9]{0,3}') | |
| sitesup=$(echo $vnet | cut -d. -f0-3) | |
| sitehop=$(echo ${sitesup}.${rsite}) | |
| ip route | grep -q "^${line}.*dev.${int}" && { | |
| ping -4 -I ${int} -c3 -A -q ${sitehop} &>/dev/null && echo "$line via ${sitehop} = still reachable" || { echo "$line via ${sitehop} = is now unreachable - removing from routing table" ; logw "$line via ${sitehop} = is now unreachable - removing from routing table" ; ip route del $(echo $line | awk '{print $1}') ;} | |
| } || { | |
| ping -4 -I ${int} -c3 -A -q ${sitehop} &>/dev/null && { echo "$line via ${sitehop} = is now reachable + adding to routing table" ; logw "$line via ${sitehop} = is now reachable + adding to routing table" ; ip route add $line dev $int ;} || echo "$line via ${sitehop} = still unreachable" | |
| } | |
| done | |
| exit | |
| } | |
| [ $1 == "help" ] && { | |
| echo -e " | |
| ┌────────────────── FreshTomato ────────────────────┐ | |
| wireguard | |
| Usage: | |
| help this screen | |
| [empty] loads the script | |
| stop to unload the config | |
| check to verify VPN enpoint reachability | |
| makeconf a wizard to create multisite config | |
| The script can be run from anywhere but expects | |
| a wg0.conf file to be present in the same folder. | |
| makeconf is a good starting point. | |
| └───────────────────────────────────────────────────┘ | |
| " | |
| exit | |
| } | |
| [ $1 == "makeconf" ] && { | |
| SCRIPT_PATH=$(dirname "$0") | |
| d="/tmp/wireguard" | |
| rm -fr $d &>/dev/null | |
| mkdir $d | |
| echo -e " | |
| ┌──────────────────────────────────────────────────────────────────────────────────────────┐ | |
| │ This script will create the configuration for your wireguard site-to-site full mesh VPN. │ | |
| │ Please follow carefully the instructions and beware: you will need to keep to hand the │ | |
| ▌ LAN subnet used by each site (/24) and define a brand new privately (rfc1918) addressed ▐ | |
| ▌ subnet /24 of choice to dedicate to the inter-VPN connectivity. The configurationis fully▐ | |
| ▌ automated including key generation, just make sure you answer the questions correctly. ▐ | |
| │ If any issue just re-run the makeconf. When finished you will just need to upload each │ | |
| │ site-specific-config to the relevant router │ | |
| └──────────────────────────────────────────────────────────────────────────────────────────┘" | |
| read -p " | |
| ┌──────┐ ┌──────┐ | |
| │ rtrA │ │ rtrB │ | |
| └──────┘\ /└──────┘ | |
| *------------------* | |
| | 192.168.253.0/24 | | |
| *------------------* | |
| ┌──────┐/ \┌──────┐ | |
| │ rtrC │ │ rtrN │ | |
| └──────┘ └──────┘ | |
| Private /24 subnet to dedicate to the VPN interconnectivity in format X.X.X.0/24 | |
| (empty uses 192.168.253.0/24) : " vpnnet | |
| [ -z $vpnnet ] && vpnnet=192.168.253.0/24 | |
| echo "vnet=$vpnnet" > $d/wireguard.TCONF | |
| read -p "Port number to be used for wireguard communication | |
| (empty uses default 51820) : " vpnport | |
| [ -z $vpnport ] && vpnport=51280 | |
| echo "port=$vpnport | |
| " >> $d/wireguard.TCONF | |
| read -p "How many sites do you want to interconnect? | |
| (default 2) : " vpnsites | |
| [ -z $vpnsites ] && vpnsites=2 | |
| read -p " | |
| How often do you want to check the status of wg? If any issue it will try to recover. | |
| (0 to disable, 15 default) 0-60min : " ansp | |
| [ -z $ansp ] && ansp=15 | |
| echo " | |
| We will now enter the site specific section of the configuration." | |
| i=1 | |
| while [ $i -le $vpnsites ]; do | |
| read -p " | |
| ┌──────────────────── | |
| │ Site $i | |
| ├──────────────────── | |
| │ port= $vpnport | |
| │ FQDN= ? | |
| Name (FQDN) of the device : " ansa | |
| read -p " | |
| ┌──────────────────── | |
| │ Site $i | |
| ├──────────────────── | |
| │ port= $vpnport | |
| │ FQDN= $ansa | |
| │ LAN= ? | |
| LAN Subnet at this site (in format X.X.X.0/24) : " ansb | |
| site=$(echo $ansb | grep -Eo '(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/..' | grep .*/24$ | cut -d. -f3) | |
| vpnip=$(echo $(echo $vpnnet | cut -d. -f1-3).${site}/24) | |
| read -p " | |
| ┌──────────────────── | |
| │ Site $i | |
| ├──────────────────── | |
| │ port= $vpnport | |
| │ FQDN= $ansa | |
| │ LAN= $ansb | |
| │ SiteRef= $site | |
| │ VPNIP= $vpnip | |
| │ port-in= ? | |
| Is port $vpnport inbound from Internet possible on this site (e.g. WAN its a public IP or a port-fowarding for $vpnport)? | |
| (default yes) y/n : " ansc | |
| [ -z $ansc ] && ansc=y | |
| # read -p "[Site $i] If this site subject to high packet loss e.g. WAN is 4G? | |
| # (default no) y/n : " ansd | |
| # [ -z $ansd ] && ansd=n | |
| echo -e "${green} | |
| ┌──────────────────── | |
| │ Site $i | |
| ├──────────────────── | |
| │ port= $vpnport | |
| │ FQDN= $ansa | |
| │ LAN= $ansb | |
| │ SiteRef= $site | |
| │ VPNIP= $vpnip | |
| │ port-in= $ansc | |
| └──────────────────── | |
| ${black}" | |
| mkdir -p $d/$ansa | |
| wg genkey > $d/${ansa}/privateKey 2>/dev/null | |
| wg pubkey < $d/${ansa}/privateKey > $d/${ansa}/publicKey 2>/dev/null | |
| echo "[interface] | |
| PrivateKey = $(cat $d/$ansa/privateKey) | |
| ListenPort = $vpnport | |
| #vnet=$vpnip | |
| #checkmin=$ansp | |
| "> $d/${ansa}/$int.conf | |
| echo "[peer] #$ansa | |
| EndPoint = $ansa | |
| PublicKey = $(cat $d/$ansa/publicKey) | |
| AllowedIPs = $vpnip, $ansb | |
| $([ $ansc == "n" ] && echo 'PersistentKeepalive = 25') | |
| " > $d/${ansa}.TEMPO | |
| i=$((i+1)) | |
| done | |
| ls -p $d | grep .*/$ | cut -d/ -f1 | while read folder; do | |
| cd $d/$folder | |
| ls -1 ../*.TEMPO | grep -v "$folder" | while read line; do cat $line >> $int.conf | |
| echo "************ 2 $d/$folder ****************" | |
| cp -f $SCRIPT_PATH/wg.sh ./wg.sh | |
| done | |
| done | |
| echo -e " | |
| ┌────────────────────────────────────────────────────────────────────────────────────────┐ | |
| ▌ ${grey}Configuration completed.${black} ▐ | |
| └────────────────────────────────────────────────────────────────────────────────────────┘ | |
| Find the each site relevant ${green}wg.sh${black} and ${green}$int.conf${black} files in:${green} | |
| $(ls -l $d | grep ^d | awk '{print "/tmp/wireguard/"$9"/"}')${black} | |
| Copy each wg.sh & $int.conf on the permanent storage of target router e.g. /jffs. | |
| Place them both in the same folder. Bring the VPN up calling /whateverpath/wg.sh | |
| NOTEs: | |
| - do not edit the wg.sh or $int.conf they are ready to be used as they are | |
| - remember to ${green}chmod +x wg.sh${black} on the target device. | |
| - to autostart you could use something like this in the Administration/script/firewall: | |
| ${green}/jffs/wg.sh${black} | |
| " | |
| find $d -name '*.TCONF' -exec rm {} + &>/dev/null | |
| find $d -name '*.TEMPO' -exec rm {} + &>/dev/null | |
| find $d -name '*Key' -exec rm {} + &>/dev/null | |
| exit | |
| } | |
| } | |
| ifconfig $int down 2>/dev/null | |
| ip link del dev $int 2>/dev/null | |
| rmmod wireguard 2>/dev/null | |
| modprobe wireguard | |
| ip link add dev $int type wireguard | |
| ip address add dev $int $vnet | |
| wg setconf $int $DIR/$int.conf | |
| sleep 1 | |
| ifconfig $int up | |
| # bypass CTF for wireguard | |
| [ $(nvram get ctf_disable) -eq 0 ] && { | |
| iptables -t mangle -nvL PREROUTING | grep -q '.*MARK.*all.*wg0.*0x1/0x7' || iptables -t mangle -I PREROUTING -i $int -j MARK --set-mark 0x01/0x7 | |
| } | |
| # open WireGuard port | |
| iptables -nvL INPUT | grep -q ".*ACCEPT.*udp.dpt.${port}$" || iptables -A INPUT -p udp --dport $port -j ACCEPT | |
| # accept packets from WireGuard internal subnet | |
| iptables -nvL INPUT | grep -q ".*ACCEPT.*all.*$int" || iptables -A INPUT -i $int -j ACCEPT | |
| # set up forwarding | |
| iptables -nvL FORWARD | grep -q ".*ACCEPT.*all.*$int" || iptables -A FORWARD -i $int -j ACCEPT | |
| rnet=$(grep -Ev '^($|#|\[)' ${DIR}/${int}.conf | grep -Eo '(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/..' | grep -v .*/32$) | |
| # add routes to opposite lan | |
| echo $rnet | tr " " "\n" | while read line; do ip route | grep -q "^${line}.*dev.$int.*" || ip route add $line dev $int; done | |
| # add periodic checks | |
| [ $checkmin -ne 0 ] && cru l | grep -q '#wireguard-check#' || cru a wireguard-check "*/${checkmin} * * * * ${DIR}/wg.sh check" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment