Skip to content

Instantly share code, notes, and snippets.

@jaxFF
Last active July 2, 2023 12:13
Show Gist options
  • Save jaxFF/36c804e21f7f2a731ad56bd09a0efed3 to your computer and use it in GitHub Desktop.
Save jaxFF/36c804e21f7f2a731ad56bd09a0efed3 to your computer and use it in GitHub Desktop.
#!/bin/bash
set -xe
cwd="$HOME/wg_data"
if [ "$(id -u)" -ne 0 ]; then echo "script must be ran under root" >&2; exit 1; fi
# TODO: don't remove last ip -- support adding clients post-install
# TODO: actually use cwd?
# upgrade kernel and install deps
sudo apt update -y && sudo apt upgrade -y
sudo apt -y install linux-image-amd64 linux-headers-amd64 wireguard qrencode iptables-persistent
client_count=2
# dynamically query the info we need
echo " [-] Generating a new server configuration"
echo "WARNING: Private and public keys may be displayed in the shell"
server_iface=$(route -n | awk '$1 == "0.0.0.0" {print $8}') #${ifaces[0]}
server_localip=$(hostname -i | awk '{print $1;}')
server_pubip=$(/sbin/ip -o -4 addr show $server_iface | sed -n 's/.* inet \(.*\)\/.*/\1/p' | head -1 )
server_privkey=$(wg genkey)
server_pubkey=$(echo "$server_privkey" | wg pubkey)
wg-quick down wg0
# postup/down here allows forwarding of IPv4 packet traffic from wg0 to eth0
# it also enables masquarading, re-writing said packets to make it appear as though
# they came from wg0 iface
cat > "wg0.conf" <<EOL
[Interface]
Address = 10.2.0.1/24
ListenPort = 51420
SaveConfig = true
PrivateKey = ${server_privkey}
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ${server_iface} -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o ${server_iface} -j MASQUERADE
EOL
mv -v wg0.conf /etc/wireguard/
chown -v root:root /etc/wireguard/wg0.conf
chmod -v 600 /etc/wireguard/wg0.conf
sysctl net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
# we append here, fine because restore should filter out duplicate rules
/sbin/iptables-save > temp_ipv4.rules
cat >> "temp_ipv4.rules" <<EOL
*filter
:FORWARD DROP [0:0]
-A INPUT -p udp -m udp --dport 51420 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -s 10.2.0.0/24 -p tcp -m tcp -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -s 10.2.0.0/24 -p udp -m udp -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -i wg0 -j ACCEPT
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -i eth0 -o wg0 -j ACCEPT
-A FORWARD -i wg0 -o eth0 -j ACCEPT
-A OUTPUT -p udp -m udp --sport 51420 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
COMMIT
EOL
/sbin/iptables-restore < temp_ipv4.rules
rm temp_ipv4.rules
netfilter-persistent save
echo iptables-persistent iptables-persistent/autosave_v4 boolean true | debconf-set-selections
wg-quick up wg0
### CLIENTS !~
if [ ! -f lastip ]; then
touch lastip
echo 10.2.0.1 > lastip
fi
echo Generating "${client_count}" unique client configs:
for i in $(seq 1 "${client_count}");
do
mkdir -p clients/$i
wg genkey | tee clients/$i/client$i | wg pubkey > clients/$i/client$i.pub
client_privkey="$(cat clients/$i/client$i)"
client_pubkey="$(cat clients/$i/client$i.pub)"
client_currip="10.2.0."$( expr $( cat lastip | tr "." " " | awk '{print $NF}' ) + 1 )
echo $client_currip > lastip
client_conf=clients/$i/client$i.conf
cat > "${client_conf}" <<EOL
[Interface]
Address = ${client_currip}/24
PrivateKey = ${client_privkey}
ListenPort = 51420
DNS = 10.2.0.1
[Peer]
PublicKey = ${server_pubkey}
Endpoint = ${server_pubip}:51420
AllowedIPs = ${client_currip}/24, 0.0.0.0/0
PersistentKeepalive = 32
EOL
tar czvf clients/client$i.tar.gz clients/$i
wg set wg0 peer $client_pubkey allowed-ips $client_currip/32
qrencode -o clients/$i/client$i.png -t ansiutf8 < "${client_conf}"
done
rm lastip
# enable the iface via sysctl and deps too
systemctl enable wg-quick@wg0
systemctl enable netfilter-persistent
wg show
### UNBOUND SETUP !~
apt install -y unbound unbound-host
curl -o /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache
cat > /etc/unbound/unbound.conf << EOL
server:
num-threads: 4
# enable logs
verbosity: 1
# list of root DNS servers
root-hints: "/var/lib/unbound/root.hints"
# use the root server's key for DNSSEC
auto-trust-anchor-file: "/var/lib/unbound/root.key"
# respond to DNS requests on all interfaces
interface: 0.0.0.0
max-udp-size: 3072
# IPs authorised to access the DNS Server
access-control: 0.0.0.0/0 refuse
access-control: 127.0.0.1 allow
access-control: 10.2.0.0/24 allow
# not allowed to be returned for public Internet names
private-address: 10.2.0.0/24
#hide DNS Server info
hide-identity: yes
hide-version: yes
# limit DNS fraud and use DNSSEC
harden-glue: yes
harden-dnssec-stripped: yes
harden-referral-path: yes
# add an unwanted reply threshold to clean the cache and avoid, when possible, DNS poisoning
unwanted-reply-threshold: 10000000
# have the validator print validation failures to the log
val-log-level: 1
# minimum lifetime of cache entries in seconds
cache-min-ttl: 1800
# maximum lifetime of cached entries in seconds
cache-max-ttl: 14400
prefetch: yes
prefetch-key: yes
EOL
chown -R unbound:unbound /var/lib/unbound
# replace systemd-resolved with unbound
systemctl stop systemd-resolved
systemctl disable systemd-resolved
systemctl enable unbound-resolvconf
systemctl enable unbound
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment