💾 Archived View for tilde.town › ~mio › log › 2024-12-04-december-adventure-2024 › wg.sh captured on 2024-12-17 at 10:20:29.

View Raw

More Information

-=-=-=-=-=-=-

#!/bin/sh
# Description: a quick Wireguard setup script.
# Version: 2024-12-01
# Initial version: 2024-11-26


# General
endpoint_type="ipv4"
net_iface="eth0"
peers=10
wg_dir="/etc/wireguard"
wg_iface="wg0"
wg_port=51820
peers_dir="$wg_dir/$wg_iface-peers"
peer_config="$peers_dir/peer=n=.conf"
peer_config_qr="$peers_dir/peer=n=-qr.conf"
peer_config_qr_on=1
peer_keepalive=30
wg_config="$wg_dir/$wg_iface.conf"

# IPv4
ipv4_on=1
ipv4_allowed_ips="0.0.0.0/0"
ipv4_dns="208.67.222.222, 208.67.220.220"
ipv4_ip="10.0.0.=n=/32"
ipv4_subnet="10.0.0.1/24"
ipv4_server_ip=$(ip r s | grep "$net_iface.*src" | sed -e "s/.*src //" | \
  cut -d" " -f1)

# IPv6
ipv6_on=1
ipv6_allowed_ips="::/0"
ipv6_dns="2620:0:ccc::2, 2620:0:ccd::2"
ipv6_ip="fddd:ddd:ddd:ddd::=n=/128"
ipv6_subnet="fddd:ddd:ddd:ddd::1/64"
ipv6_server_ip=$(ip -6 r s | grep "$net_iface.*src" | sed -e "s/.*src //" | \
  cut -d " " -f1)

# System paths
modules="/etc/modules"
iptables="/usr/sbin/iptables"
ip6tables="/usr/sbin/ip6tables"
net_interfaces="/etc/network/interfaces"
qrencode="/usr/bin/qrencode"
sysctl="/sbin/sysctl"
sysctl_config="/etc/sysctl.conf"
wgquick="/usr/bin/wg-quick"


msg() { echo "$1"; }


msg "Adding tun to $modules"
modprobe tun
tun_added=$(grep "tun" $modules)
test -z $tun_added && echo "tun" >> $modules


msg "Installing packages"
# Remove the wireguard package between new installations, to avoid wg-quick
# adding incorrect drop rules to the firewall.
test -f $wgquick && apk del wireguard-tools-wg-quick
test -f $wgquick || \
  apk add iptables iptables-openrc procps-ng wireguard-tools-wg-quick
if [ "$peer_config_qr_on" -eq 1 ] && [ ! -f $qrencode ]; then
  apk add libqrencode-tools
fi


if [ "$ipv4_on" -eq 1 ]; then
  msg "Enabling packet forwarding over ipv4"
  ipv4_forward_on=$(grep "net.ipv4.ip_forward" $sysctl_config)
  if [ -z "$ipv4_forward_on" ]; then
    echo "net.ipv4.ip_forward = 1" >> $sysctl_config
  else
    sed -i "s/net\.ipv4\.ip_forward = 0/net\.ipv4\.ip_forward = 1/" \
      $sysctl_config
    sed -i "s/net\.ipv4\.ip_forward=0/net\.ipv4\.ip_forward=1/" \
      $sysctl_config
  fi
fi


if [ "$ipv6_on" -eq 1 ]; then
  msg "Enabling packet forwarding over ipv6"
  ipv6_forward_on=$(grep "net.ipv6.conf.all.forwarding" $sysctl_config)
  if [ -z "$ipv6_forward_on" ]; then
    echo "net.ipv6.conf.all.forwarding = 1" >> $sysctl_config
  else
    sed -i "s/net\.ipv6\.conf\.all\.forwarding = 0/net\.ipv6\.conf\.all\.forwarding = 1/" \
      $sysctl_config
    sed -i "s/net\.ipv6\.conf\.all\.forwarding=0/net\.ipv6\.conf\.all\.forwarding=1/" \
      $sysctl_config
  fi
fi


msg "Enabling sysctl"
$sysctl -p $sysctl_config
rc-update add sysctl
rc-service sysctl status


msg "Generating server keys"
test -d $wg_dir || mkdir -p $wg_dir
umask 077 $wg_dir
_server_privkey="$(wg genkey)"
_server_pubkey="$(echo "$_server_privkey" | wg pubkey)"


msg "Creating server config at $wg_config"
# Set server address
_server_addr=$ipv4_subnet
if [ "$ipv4_on" -eq 1 ] && [ "$ipv6_on" -eq 1 ]; then
  _server_addr="$ipv4_subnet, $ipv6_subnet"
elif [ "$ipv4_on" -eq 0 ] && [ "$ipv6_on" -eq 1 ]; then
  _server_addr=$ipv6_subnet
fi

cat << EOF > $wg_config
[Interface]
Address = $_server_addr
ListenPort = $wg_port
PrivateKey = $_server_privkey
EOF

_ipts="$iptables $ip6tables"
for i in $_ipts; do
  _ipt_add=0
  if [ "$i" == "$iptables" ] && [ "$ipv4_on" -eq 1 ]; then _ipt_add=1; fi
  if [ "$i" == "$ip6tables" ] && [ "$ipv6_on" -eq 1 ]; then _ipt_add=1; fi
  if [ "$_ipt_add" -eq 1 ]; then
    _ipt=$(basename $i)
    cat << EOF >> $wg_config
PostUp = $_ipt -I INPUT -p udp -m udp --dport $wg_port -j ACCEPT
PostUp = $_ipt -A FORWARD -i %i -j ACCEPT
PostUp = $_ipt -t nat -A POSTROUTING -o $net_iface -j MASQUERADE
PostUp = $_ipt -A FORWARD -o %i -j ACCEPT
PostDown = $_ipt -D INPUT -p udp -m udp --dport $wg_port -j ACCEPT
PostDown = $_ipt -D FORWARD -i %i -j ACCEPT
PostDown = $_ipt -t nat -D POSTROUTING -o $net_iface -j MASQUERADE
PostDown = $_ipt -D FORWARD -o %i -j ACCEPT
EOF
  fi
done
chmod 600 $wg_config


msg "Generating peer keys"
test -d $peers_dir || mkdir -p $peers_dir
umask 077 $peers_dir

# Set allowed IPs, DNS, endpoint
_allowed_ips=$ipv4_allowed_ips
_dns=$ipv4_dns
if [ "$ipv4_on" -eq 1 ] && [ "$ipv6_on" -eq 1 ]; then
  _allowed_ips="$ipv4_allowed_ips, $ipv6_allowed_ips"
  _dns="$ipv4_dns, $ipv6_dns"
elif [ "$ipv4_on" -eq 0 ] && [ "$ipv6_on" -eq 1 ]; then
  _allowed_ips=$ipv6_allowed_ips
  _dns=$ipv6_dns
fi
_endpoint="$ipv4_server_ip:$wg_port"
if [ "$ipv6_on" -eq 1 ] && [ "$endpoint_type" == "ipv6" ]; then
  _endpoint="[$ipv6_server_ip]:$wg_port"
fi

n=1; while [ $n -le $peers ]; do
  # Last octet of IP starts at .2
  _octet=$(( n + 1 ))

  # Set address
  _addr=${ipv4_ip/=n=/$_octet}
  if [ "$ipv4_on" -eq 1 ] && [ "$ipv6_on" -eq 1 ]; then
    _addr="${ipv4_ip/=n=/$_octet}, ${ipv6_ip/=n=/$_octet}"
  elif [ "$ipv4_on" -eq 0 ] && [ "$ipv6_on" -eq 1 ]; then
    _addr=${ipv6_ip/=n=/$_octet}
  fi

  # Generate peer keys
  _peer_privkey="$(wg genkey)"
  _peer_pubkey="$(echo "$_peer_privkey" | wg pubkey)"
  _peer_prekey="$(wg genpsk)"

  msg "Creating peer config ${peer_config/=n=/$n}"
  cat << EOF > ${peer_config/=n=/$n}
[Interface]
Address = $_addr
DNS = $_dns
PrivateKey = $_peer_privkey

[Peer]
PublicKey = $_server_pubkey
PresharedKey = $_peer_prekey
AllowedIPs = $_allowed_ips
PersistentKeepalive = $peer_keepalive
Endpoint = $_endpoint
EOF

  if [ "$peer_config_qr_on" -eq 1 ] && [ -f $qrencode ]; then
    msg "Generating QR code file for ${peer_config/=n=/$n}"
    $qrencode -t UTF8 "$(cat ${peer_config/=n=/$n})" > ${peer_config_qr/=n=/$n}
  fi

  msg "Adding peer to $wg_config"
  cat << EOF >> $wg_config

[Peer]
PublicKey = $_peer_pubkey
PresharedKey = $_peer_prekey
AllowedIPs = $_addr
EOF

  _peer_privkey=""
  _peer_pubkey=""
  _peer_prekey=""
  n=$(( n + 1 ))
done


wg_in_ifaces=$(grep "iface $wg_iface" $net_interfaces)
if [ -z "$wg_in_ifaces" ]; then
  msg "Adding $wg_iface to $net_interfaces"
  cat << EOF >> $net_interfaces

auto $wg_iface
iface $wg_iface inet static
pre-up wg-quick up $wg_config
EOF
fi


msg "Starting $wg_iface"
wg-quick up $wg_iface