# ██████ ██ ▄█▀▒███████▒ █ █░ ▄████ #▒██ ▒ ██▄█▒ ▒ ▒ ▒ ▄▀░ ▓█░ █ ░█░ ██▒ ▀█▒ #░ ▓██▄ ▓███▄░ ░ ▒ ▄▀▒░ ░█▒░ █ ▒█░ █░█ ▒ ██░▄▄▄░ # ▒ ██▒▓██ █▄ ▄▀▒ ░ ░█░ █ ░█ ░▓█ ██▓ #▒██████▒▒▒██▒ █▄▒███████▒ ░░██▒██▓ ░▒▓███▀▒ #▒ ▒▓▒ ▒ ░▒ ▒▒ ▓▒░▒▒ ▓░▒░▒ ░ ▓░▒ ▒ ░▒ ▒ #░ ░▒ ░ https://git.sk4.nz/sk4nz/skz-wg ░ ░ # ░ ░ ░ ░ ░ ░ .PHONY: clean deps info restart #.SILENT: # ░▒▓█ CONFIGURATION █▓▒░ # Change this list to always create clients # CLIENTS= client1 client2 CLIENTS?= .poison empty (CLIENTS) # Install packages, always keep this line before the next block (for curl) INSTALLPKG!= [ -f .installed ] || (pkg_add -I wireguard-tools libqrencode curl && touch .installed) # Network configuration SERVER?!= curl -s ifconfig.co WG_PORT= 5353 WG_LAN= 10.10.10.1/24 WAN!= route -n show -inet | grep default | awk '{print $$NF}' # Packet Filter configuration for allowed ports OUT_TCP= http ftp whois https ssh IN_TCP= http https ssh OUT_UDP= domain ntp $(WG_PORT) IN_UDP= $(WG_PORT) VPN_TCP= $(IN_TCP) # Server private key WG_KEY!= cat server.key 2> /dev/null || wg genkey .poison empty $(WG_KEY) # Ads lists ADS_URLS= https://winhelp2002.mvps.org/hosts.txt ADS_URLS+= https://pgl.yoyo.org/as/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext ADS_URLS+= https://adaway.org/hosts.txt ADS_URLS+= https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts # ░▒▓█ TARGETS █▓▒░ all: /etc/pf.wg /var/unbound/etc/unbound.conf # Enable IPv4 forwarding permanently, if not already grep forwarding /etc/sysctl.conf 2> /dev/null || (printf 'net.inet.ip.forwarding=1\n' >> /etc/sysctl.conf && sysctl net.inet.ip.forwarding=1) # Write new pf.conf grep 'pf.header' /etc/pf.conf || printf 'include "/etc/pf.header"\n' > /etc/pf.conf grep 'pf.wg' /etc/pf.conf || printf 'include "/etc/pf.wg"\n' >> /etc/pf.conf # Validate and start new pf.conf pfctl -nf /etc/pf.conf && pfctl -f /etc/pf.conf # Restart the WireGuard interface $(MAKE) restart $(MAKE) info restart: sh /etc/netstart wg0 /etc/pf.bogons: # Reserved IP addresses to drop, see https://en.wikipedia.org/wiki/Reserved_IP_addresses printf '0.0.0.0\ \n10.0.0.0/8\ \n100.64.0.0/10\ \n127.0.0.0/8\ \n128.0.0.0/16\ \n169.254.0.0/16\ \n172.16.0.0/12\ \n191.255.0.0/16\ \n192.0.0.0/24\ \n192.0.2.0/24\ \n192.88.99.0/24\ \n192.168.0.0/16\ \n198.18.0.0/15\ \n198.51.100.0/24\ \n203.0.113.0/24\ \n223.255.255.0/24\ \n224.0.0.0/4\ \n240.0.0.0/4\ \n255.255.255.255\n' > $@ /etc/pf.abuse_ssh /etc/pf.abuse_tcp: # Anti-DDoS persistent tables touch $@ /etc/pf.header: # The original pf header printf 'set skip on lo\nblock return\npass\ \nblock return in on ! lo0 proto tcp to port 6000:6010\ \nblock return out log proto {tcp udp} user _pbuild\n' > $@ /etc/pf.wg: /etc/pf.bogons /etc/pf.abuse_ssh /etc/pf.abuse_tcp /etc/pf.header /etc/pf.conf.orig # Define allowed PF ports printf 'out_tcp_ports = "{ $(OUT_TCP) }"\ \nout_udp_ports = "{ $(OUT_UDP) }"\ \nvpn_tcp_ports = "{ $(VPN_TCP) }"\ \nin_tcp_ports = "{ $(IN_TCP) }"\ \nin_udp_ports = "{ $(IN_UDP) }"\n' > $@ # Rules printf '# BEGIN PF.WG\ \n### Macros \ \n# statefull tracking options - sto\ \n# SSH is considered under abuse when there are more than 6 connections per minute \ \nssh_sto = "(max-src-conn-rate 6/60, overload flush global)"\ \n# TCP is considered under abuse when there are more than 300 simultaneous connections or 600 per minute\ \ntcp_sto = "(max-src-conn 300, max-src-conn-rate 600/60, overload flush global)"\ \n# TCP flags \ \nflag_syn = "flags S/SA modulate state"\ \n# define e (egress) and i (ingress) macros\ \nedropin = "block drop in quick on egress from"\ \nedropout = "block drop out log quick on egress from"\ \nepassout = "pass out log on egress proto tcp to any port"\ \ninblocktcp = "block in log quick proto tcp from"\ \ninpasstcp = "pass in on egress proto tcp to any port"\ \ninvpntcp = "pass in log on wg0 proto tcp to any port"\ \n# Persitent tables\ \ntable persist file "/etc/pf.bogons"\ \ntable persist file "/etc/pf.abuse_tcp"\ \ntable persist file "/etc/pf.abuse_ssh"\ \n# Various security-related options\ \nset block-policy return\ \nset optimization conservative\ \nset reassemble yes\ \nset syncookies adaptive (start 25%%, end 12%%)\ \nset ruleset-optimization profile\ \nset skip on lo\ \nantispoof for { lo, egress }\ \nmatch in all scrub (max-mss 1440 no-df random-id reassemble tcp)\ \n### Rules \ \n# Prevent dns leaks \ \nblock in log on egress inet proto { tcp udp } from any to ! egress port 53\ \n# Block bogons - DEACTIVATED \ \n# TODO : change pf.bogons to allow LAN\ \n#$edropin { } to any\ \n#$edropout any to { }\ \n# block abusers\ \n$inblocktcp to any port ssh\ \n$inblocktcp to any port $in_tcp_ports\ \n# Default rule : block stateless traffic\ \nblock\ \n# Enable ICMP echo request, reply, unreach\ \npass quick inet proto icmp all icmp-type { echoreq, echorep, unreach }\ \n# Enable IPv4 traceroute\ \npass out on egress proto udp to port 33433:33626\ \n# Pass ingress \ \n$inpasstcp ssh $$flag_syn $$ssh_sto\ \n$inpasstcp http $$flag_syn $$tcp_sto\ \n$inpasstcp https $$flag_syn $$tcp_sto\ \n$invpntcp $$vpn_tcp_ports $$flag_syn $$tcp_sto\ \npass in on egress proto udp to any port $$in_udp_ports\ \n# Pass egress\ \n$epassout $$out_tcp_ports $$flag_syn\ \npass out on egress proto udp to any port $$out_udp_ports allow-opts\ \n# Pass Wireguard-LAN\ \npass out log on wg0 proto tcp to any port $$vpn_tcp_ports\ \npass in on wg0 proto udp to any port $$out_udp_ports allow-opts\ \n# END PF.WG\n' >> $@ # NAT the WireGuard interface to WAN printf 'pass out on $(WAN) inet from wg0:network to any nat-to ($(WAN))' >> $@ ad-blacklist: rm -rf /var/unbound/ad-blacklist.conf $(MAKE) /var/unbound/ad-blacklist.conf /var/unbound/ad-blacklist.conf: # For the lying DNS resolver for url in "$(ADS_URLS)"; do curl -s $$url >> /tmp/ads-daily; done awk -v white='/(api.solvemedia.com)/' '$$1 ~ /^127\.|^0\./ && $$2 !~white {gsub("\r",""); print tolower($$2)}' /tmp/ads-daily | sort | uniq | awk '{printf "server:\n", $$1; printf "local-data: \"%s A 127.0.0.1\"\n", $$1}' > $@ rm -rf /tmp/ads-daily # Update lists daily grep 'ad-blacklist' /etc/daily.local || printf 'make -C $(PWD) ad-blacklist\nrcctl restart unbound\n' >> /etc/daily.local /etc/pf.conf.orig: # Save original pf.conf cp /etc/pf.conf $@ /etc/hostname.wg0: server.key $(CLIENTS) # The WireGuard interface configuration printf 'wgkey "$(WG_KEY)"\ \nwgport $(WG_PORT)\ \ninet $(WG_LAN)\n' > $@ # Add peers for cli in $(CLIENTS); do \ N=$$(sha256 -qs $$cli | cut -b 1-2);\ PUB=$$(cat $$cli/$$cli.pub);\ PSK=$$(cat $$cli/$$cli.psk);\ printf "# $$cli\nwgpeer \"$$PUB\" wgpsk \"$$PSK\" wgpka 25 wgaip $(WG_LAN:H:S/.1$/./)"$$(printf $$((0x$$N)))"/32\n" >> $@;\ done printf 'up\n' >> $@ chmod 640 $@ # Start the wg interface sh /etc/netstart wg0 /var/unbound/etc/unbound.conf: /etc/hostname.wg0 ad-blacklist # Unbound configuration, with lying DNS and DNSSEC validation printf 'server:\ \n\tinterface: 127.0.0.1\ \n\tinterface: $(WG_LAN:H)\ \n\tdo-ip6: no\ \n\taccess-control: 0.0.0.0/0 refuse\ \n\taccess-control: 127.0.0.0/8 allow\ \n\taccess-control: $(WG_LAN) allow\ \n\tauto-trust-anchor-file: "/var/unbound/db/root.key"\ \n\taggressive-nsec: yes\ \n\tinclude: /var/unbound/ad-blacklist.conf\ \n\nremote-control:\ \n\tcontrol-enable: yes\ \n\tcontrol-interface: /var/run/unbound.sock\n' > $@ rcctl enable unbound rcctl start unbound info: printf '\033[1mWireguard: \033[32m$(SERVER):$(WG_PORT) \033[0m$(WG_LAN)\n' T=$$(wg show all transfer); for cli in $(CLIENTS); do\ N=$$(sha256 -qs $$cli | cut -b 1-2);\ PUB=$$(cat $$cli/$$cli.pub);\ IN=$$(printf "$$T\n" | grep $$PUB | awk '{print $$(NF-1)}');\ OUT=$$(printf "$$T\n" | grep $$PUB | awk '{print $$(NF)}');\ printf '- \033[1m\033[33m%15s\033[0m $(WG_LAN:H:S/.1$/./)%-3s in: %-10s out: '$$OUT'\n' $$cli $$(printf $$((0x$$N))) $$IN;\ done server.conf: server.pub # Generate the server configuration header (deprecated) printf '[Interface] # VOID - Tunnel gateway: $(WG_LAN:H)\n#Address = $(WG_LAN:H)\nListenPort = $(WG_PORT)\nPrivateKey = '$$(cat server.key)'\n' > server.conf; server.key: # Generate server private key if not already present printf $(WG_KEY) > $@ chmod 600 $@ server.pub: server.key # Generate server pub key if not already present cat server.key | wg pubkey > $@ chmod 600 $@ $(CLIENTS): server.conf mkdir -p $@ # Generate priv/pub keys wg genkey | tee $@/$@.key | wg pubkey > $@/$@.pub # Generate PSK touch $@/$@.psk && chmod 600 $@/$@.psk wg genpsk > $@/$@.psk # Append to server.conf (deprecated) and the client configuration PSK=$$(cat $@/$@.psk); PUB=$$(cat $@/$@.pub); N=$$(sha256 -qs $@ | cut -b 1-2);\ echo -e '[Peer] # '$@'\nAllowedIPs = $(WG_LAN:H:S/.1$/./)'$$(echo $$((0x$$N)))'/32\nPublicKey = '$$PUB'\nPresharedKey = '$$PSK'\n' >> server.conf;\ echo -e '[Interface] # Local tunnel address: $(WG_LAN:H:S/.1$/./)'$$(echo $$((0x$$N))) router: $(WG_LAN:H)'\nAddress = $(WG_LAN:H:S/.1$/./)'$$(echo $$((0x$$N)))/32'\nPrivateKey = '$$(cat $@/$@.key)'\nDNS = $(WG_LAN:H)\n[Peer] # Tunnel endpoint: $(SERVER)\nEndpoint = $(SERVER):$(WG_PORT)\nPublicKey = '$$(cat server.pub)'\nPresharedKey = '$$PSK'\nAllowedIPs = 0.0.0.0/0' > $@/$@.conf cat $@/$@.conf | qrencode -t ansiutf8 -o $@/$@.qr chmod -R 600 $@ clean: -ifconfig wg0 down -rcctl stop unbound -rcctl disable unbound -rm -rf $(CLIENTS) *.key *.pub server.conf /var/unblound/ad-blacklist.sh /etc/pf.wg /etc/hostname.wg0 /var/unbound/etc/unbound.conf /etc/pf.header -sed -i '/ad-blacklist/d' /etc/daily.local -sed -i '/rcctl restart unbound/d' /etc/daily.local -cp /etc/pf.conf.orig /etc/pf.conf pfctl -nf /etc/pf.conf && pfctl -f /etc/pf.conf