{"id":27160382,"url":"https://github.com/betterwayelectronics/secure-wireguard-implementation","last_synced_at":"2025-04-08T23:45:06.746Z","repository":{"id":43037888,"uuid":"287882174","full_name":"BetterWayElectronics/secure-wireguard-implementation","owner":"BetterWayElectronics","description":"A guide on implementing a secure Wireguard server on OVH (or any other Debian VPS) with DNSCrypt, Port Knocking \u0026 an SSH-Honeypot","archived":false,"fork":false,"pushed_at":"2024-06-20T04:45:54.000Z","size":1477,"stargazers_count":373,"open_issues_count":3,"forks_count":38,"subscribers_count":22,"default_branch":"master","last_synced_at":"2025-04-08T23:44:57.300Z","etag":null,"topics":["ddos","dnscrypt","dnscrypt-service","honeypot","iptables","knocking","ovh","port","secure","self-hosted","server","ssh","ssh-server","tunnel","vps","wireguard"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BetterWayElectronics.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-16T05:46:31.000Z","updated_at":"2025-03-31T19:23:48.000Z","dependencies_parsed_at":"2024-11-01T11:30:34.677Z","dependency_job_id":"0f591870-51fc-476d-a053-fcd0b30ae6c1","html_url":"https://github.com/BetterWayElectronics/secure-wireguard-implementation","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterWayElectronics%2Fsecure-wireguard-implementation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterWayElectronics%2Fsecure-wireguard-implementation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterWayElectronics%2Fsecure-wireguard-implementation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterWayElectronics%2Fsecure-wireguard-implementation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BetterWayElectronics","download_url":"https://codeload.github.com/BetterWayElectronics/secure-wireguard-implementation/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247947821,"owners_count":21023058,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ddos","dnscrypt","dnscrypt-service","honeypot","iptables","knocking","ovh","port","secure","self-hosted","server","ssh","ssh-server","tunnel","vps","wireguard"],"created_at":"2025-04-08T23:45:06.068Z","updated_at":"2025-04-08T23:45:06.730Z","avatar_url":"https://github.com/BetterWayElectronics.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# A Comprehensive Guide On WireGuard/DNSCrypt/SSH/Honeypot Implementation on OVH (Or any other Debian VPS) #\n\n### Introduction ###\n\nThe plan in this guide is to create a secure WireGuard VPN which has its\nown embedded DNSCrypt DNS resolver, this ensures that all connections\nincluding DNS requests made by the user are tunnelled through the VPS\nand is encrypted end to end. This is also expanded to include security\nthat resolves around this process making the server as secure as\npossible from external agents. The following represents the proposed\nnetwork diagram for this guide.\n\n![](media/image1.jpeg)\n\nWhy use WireGuard? As you can see in the image after this paragraph,\nwhilst on the WireGuard VPN speed decrease against a direct connection\nto the internet is negligible (~3Mbps), this is because WireGuard runs\nwithin the kernel space and thus ensures the secure tunnel can run at\nhigh speed, it is even now part of the latest Linux Kernel 5.6. But\nwhile this was my personal reason for implementing WireGuard there is\nalso the benefits in its simplicity in both development, with a lean\ncodebase of 4000 lines (compared to 100,000 in OpenVPN) but also in its\nimplementation -- which will be illustrated in this guide.\nFundamentally, you install the service and a client and exchange keys;\nit can't be easier than that. WireGuard also supports better\ncryptographic methodologies than OpenVPN and easier to expand and\ndistribute among peers.\n\n![](media/image2.png)\n\n### Buying and setting up the VPS ###\n\n![](media/image3.jpeg)\n\nTo start this project you need your own virtual private server (VPS), I\nrecommend OVHcloud https://ovh.com.au/ and their cheapest\nstarter package which is $5.00AUD a month. You get 2 GB of memory which\nis more than enough to host multiple clients on the VPN. You can generally\nchoose what operating system you want, or upload your own ISO, but in this\nexample I have chosen Debian 10. Once paid for you will receive your IP address, \nusername and password which you'll use to connect to the server. This can either be\nvia the KVM (so terminal within the browser, or VNC if they've provided it) or directly\nvia SSH using the details they've provided.\n\nBe sure to issue `apt update` and `apt upgrade` and do this regularly. I also recommend changing\nthe password that they give you and securing your account in the method you prefer.\n\nThe first thing to do is to now secure the SSH connection and ultimately\ncustomise it.\n\nStart by installing fail2ban, an active intrusion detection system\ndesigned to ban brute force attempts towards your SSH. Issue the\nfollowing commands to install fail2ban:\n\n-   `apt install fail2ban`\n\n-   `cp /etc/fail2ban/fail2ban.conf /etc/fail2ban/fail2ban.local`\n\n-   `cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local`\n\nOnce this is done you'll need to modify the `/etc/fail2ban/jail.local`\nfile to adjust the time limits, this will mean that users whom attempt\nto login to your SSH will get banned for x period of time after x\nattempts etc.\n\n![](media/image4.jpeg)\n\nFrom here you can issue the command `systemctl status fail2ban.service`\nto confirm the service is indeed running. You can also view the IP's\nthat are currently banned with the command `fail2ban-client status\nsshd`, through the iptable rules or view the log file directly at\n`/var/log/fail2ban.log`.\n\n![](media/image5.jpeg)\n\nAnother important step is to change the default SSH port of 22 to\nsomething else. This will aid in preventing automated bots from scanning\nyour VPS, though it would not prevent somebody from discovering it\neventually. This can be done by modifying the SSH config file at\n`/etc/ssh/sshd_config`. Don't forget to update your fail2ban to suit the\nchange (and restart it), but I have noticed that fail2ban does not seem to enjoy being\nmodified after the fact. If this is the case for you just modify the\niptables manually. To delete the original rule, find its number with\n`iptables -L -v -n --line-numbers` and deleting it with `iptables -D\nINPUT #`. Now to add your bespoke SSH port with fail2ban issue the\nfollowing command `iptables -A INPUT -p tcp --dport SSHPORT# -j\nf2b-sshd`.\n\n![](media/image6.jpeg)\n\n### Who Are You?? ###\n\nWell okay, so you've setup fail2ban and the whole time you've likely been root.\nWell for the next phase you have the choice to continue entirely as root, or make\na seperate account and sudo root instead. The security implications are for you to\nresearch, but in my case I have chosen to login to the server not via root, but\nwith an account with no sudo access whatsoever. From there I log into root.\nI feel this adds another tiny extra little itsy bitsy layer of protection should my\nkeys for SSH be divulged. So what did I do? Well first I changed the default root password\nwith `sudo passwd` then I made a new blank user with `sudo adduser debian`. Now I can\nswap between the accounts by issuing the `su` command. So `su debian` or just `su` to get back\nto root. Easy!\n\n### Password-free Entry (Windows) ###\n\nThe next step is to be able to login to the VPS without a password or\neven a password prompt (although this is optional), thus we would need\nto use SSH key pairs. This can be generated from Windows or within Linux\ndirectly. The first step in achieving this is to disable password\nauthentication within the SSH config file, so after modifying the port\nscroll down modify the following two settings `PasswordAuthentication\nno` and `UsePAM no`. At the bottom of the configuration file add the\nfollowing `AuthenticationMethods publickey`. If you are not going to log in\nas root, it is important to change the setting here, so comment out `PermitRootLogin`. \nSave the configuration file but do not close or reset the current PuTTY session as you have not setup the keys! \nWorst case scenario you can still access your server through the KVM console within the OVH website.\n\nNow the keys need to be generated. Continuing with an example from\nWindows, launch the PuTTY Key Generator and generate the public/private\nkey pair without a password.\n\n![](media/image7.jpeg)\n\nOnce this is done save both the public and private keys. I recommend copying and pasting\nfrom the window itself as that is the correct format for the key to be in. Saving it by clicking\non the button saves it in a different format and you'll get a refusal error from the server.\nThe public key must be saved as `authorized_keys` and the private key will can saved with a filename of\nyour choosing (ending in .ppk, the PuTTY format). To ensure future\ncompatibility be sure to click on the conversions option and select\nexport what you have generated as OpenSSH key, again without a password.\n\nNow you have to upload the public key, `authorized_keys`, to the VPS. This can be achieved\nusing PuTTY's SCP tool by issuing the following command from the Windows\nconsole `pscp c:\\documents\\authorized_keys debian@example.com:/home/debian/.ssh`.\nOr you could simply copy the public key from within the PuTTY Key Generator and paste it.\nThis is possible because if you're logged into the server via PuTTY it will allow you to paste.\nSo make the `.ssh` diretory within your user, make an `authorized_keys` file within it and paste!\n\nNow in order to connect from Windows using PuTTY you have to select the\nprivate key from within the application.\n\n![](media/image8.jpeg)\n\nAt this point you should restart the SSH service with the command\n`systemctl restart sshd`. Open another PuTTY session with the\nappropriate private key added and attempt to connect to the server. If\nall goes well you will be prompted for a username and will be instantly\nlogged in. Should you not have a private key set you will be given the\nfollowing message instead.\n\n![](media/image9.jpeg)\n\n### Password-free Entry (Linux) ###\n\nSo you want to generate the public and private key for SSH within Linux? Well!\nEither from within the server or on a client Linux machine you must generate the key pair.\nThis is done by running `ssh-keygen -t rsa` it will then prompt you for a filename, keep the default of `id_rsa`.\nIf you want to go password-free then simply don't enter one and continue.\nIt will then generate the private key and the public key, `id_rsa.pub`. Now you have to move this public key to the server, this can be done much like the earlier examples with SCP. Move the key to the directory `home/username/.ssh/` and rename it to `authorized_keys`. Now change its permissions with `chmod 700 authorized_keys`.\n\nBack on the client machine do the same process and move the `id_rsa` into the same folder and change it to the same permission. Now if you've installed knocking, then knock the server, but if you havent simply access the server with `ssh -vvv username@SERVERIP -p SSHPORT`. The `-vvv` will show you any issues you may encounter and will help diagnose any connection issues. If all went well you will have a prompt for the server as the user you logged in as, without a password!\n\n### Port Knocking ###\n\nNow it's time to setup port knocking. This will ensure that along with a\ndifferent SSH port number, it will remain blocked in the iptables (to be\nsetup next) unless a specific sequence of ports are 'knocked'. Only then\nthe iptables will allow the SSH port to be open to the IP address of the\nknocker. So the first step is to simply install the service required\nwith the command `apt-get install knockd`. Now before its run its\nimportant to modify the default settings, the service even has a\nstarting flag hidden away in a different file that must be changed prior\nto being started for the first time. The configuration file is in\n`/etc/knockd.conf` and this is my recommended bespoke settings:\n\n![](media/image10.jpeg)\n\nWhat these settings achieve is the need to knock in the sequence 1337,\n8888 and 1200 within 5 seconds of each other (Can be any sequence and\namount of ports you wish). When this is done the IP address of the one\nwho knocked will be added to the iptables, allowing exclusive access to\nport 88 (or whatever port you set SSH to). It will also only accept TCP\nSYN packets. After 15 seconds the IP that was added to the iptables will\nbe removed -- this won't log you out of the SSH session but it will\nprevent you from logging back in without knocking again, this is easier\nthan the default settings which require the user to knock the SSH port\nshut, which can be easily forgotten.\n\nNow access the following file `/etc/default/knockd` and change\n`START_KNOCKD` to `1`. Then start the knockd service by running\n`systemctl start knockd`. From this point onwards you will not be able\nto access the SSH normally (Well after you've finished setting up IP Tables). \nNote that according to the rules, the IP that knocked is the IP that will be \nadded to the iptables -- remember to be mindful of this. \nThis will be modified again after WireGuard is installed. \n\nOnce this is set up install knockd on another Linux machine\nand issue the command `knock -v IP PORT1 PORT2` to open SSH or for\nWindows download the application `BwE Port Knocker` (available on my\nGitHub) which I developed for this very write-up. This will be vital to\ngetting back into the VPS. Again, should there be a situation where you\ncannot login you still can via the KVM console.\n\n![](media/image11.jpeg)\n\n### IP Tables ###\n\n![](media/newiptables.jpg)\n\nThe next stage, as you can see in the above screenshot is to have\nappropriate set of iptables. Creating this is an iterative process,\nadding rules, testing them and eventually getting to the point where\nyour default policy can be DROP (even for output, if you want to be\nenthusiastic). The following is a list of iptables I had created for\nthis project, note that port 88 (my SSH port) is not included, this is \nbecause the rules are now handled by the knockd service, assuming you \nhave set it up properly and it is functional.\n\nI really suggest you learn how to do iptables yourself rather than just copying\nwhat I have below, but ultimately as long as you understand it you should be fine.\nIt also might be best to do this via the KVM, just in case you lock yourself out of SSH.\n\n-  `sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT`\n-  `sudo iptables -A INPUT -s 10.0.0.0/24 -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT`\n-  `sudo iptables -A INPUT -s 127.0.0.1/32 -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT`\n-  `sudo iptables -A INPUT -i lo -j ACCEPT`\n-  `sudo iptables -A INPUT -p udp -m udp --dport 51820 -m conntrack --ctstate NEW -j ACCEPT`\n-  `sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT`\n-  `sudo iptables -A FORWARD -i wg0 -j ACCEPT`\n-  `sudo iptables -A OUTPUT -o lo -j ACCEPT`\n-  `sudo iptables -P INPUT DROP`\n-  `sudo iptables -P FORWARD DROP`\n-  `sudo iptables -P OUTPUT ACCEPT`\n\nThe rules are straight forward and somewhat readable. It allows INPUT\nand FORWARD connections which are related and established to continue.\nIt allows the UDP connection of WireGuard on port 51820. It allows what\nwill become WireGuard's interface ip 10.0.0.1/24 to allow DNS and also\nits interface. It also allows the local host access to port 53 (DNSCrypt). \nAll of these services are yet to be installed at this point, thus showing the \niptables in one go is not really descriptive of how it will be implemented. \n\nAgain, it must be done iteratively with each installation of each service to ensure\nfunctionality. Once you have a functional iptables it is best to make\nthem persistent by running the following commands `apt-get install\niptables-persistent` and `systemctl start netfilter-persistent.service`. If\nyou make any changes run `sudo dpkg-reconfigure iptables-persistent`.\n\n### Host Provided Firewall/DDoS Mitigation ###\n\n![](media/image14.jpeg)\n\nWithin OVH's Manage IP's section there is the ability to change the DDoS\nmitigation from Automatic to Permanent. There is also the ability to\ncustomise their firewall. Both of these are highly recommended to add to\nyour service as even without advertising your server, it will likely\nsuffer a DDoS attack, if not multiple throughout its lifetime. As you\ncan see in the graph below, I had no attacks on my VPS and thus the\ntraffic was not very exciting, until suddenly I was hit with 80,000,000\nbytes per second. I then enabled the firewall and changed the mitigation\nto Permanent, and after that I had no down-time, though would still\nsuffer speed drops from time to time.\n\n![](media/image15.png)\n\nTheir firewall acts as a giant filter and allows only for the traffic I\nhave specified to continue through, and in my case I had only enabled\nWireGuard's port -- given that I will literally only be using that\nsingle port as it will become the port for the VPN, DNS and SSH. Though\nif I need to I could also enable the DNS port, but I have not needed to\nthus far.\n\n## DNSCrypt ##\n\nInstalling this on the VPS allows full ownership over DNS traffic both for your Wireguard client/s and the local network. \nYour DNS traffic will be forwarded to DNSCrypt which will in turn facilitate DNSSEC and the encryption of DNS requests. \nNow the next thing to step is to install `DNSCrypt-Proxy` itself.\n\nYou must first add the repositories required for installing either the testing or unstable version\nthis is done by running the following two commands.\n\n-  `echo \"deb https://deb.debian.org/debian/ testing main\" | sudo tee /etc/apt/sources.list.d/testing.list`\n-  `echo \"deb https://deb.debian.org/debian/ unstable main\" | sudo tee /etc/apt/sources.list.d/unstable.list`\n\nYou can then choose to install either one, but realistically they will likely be the same. Testing though would\nbe your safest bet. I personally find that the stable version is simply too old and ironically unstable.\n\nStart with `sudo apt update \u0026\u0026 \\` and then in the prompt type in `sudo apt install -t testing dnscrypt-proxy`\n\nIt is recommended then to reset and delete `/etc/apt/sources.list.d/testing.list`.\n\nThe next step then is to configure DNSCrypt, first run `nano /etc/dnscrypt-proxy/dnscrypt-proxy.toml`\nand modify the `listen_address` line to be `[]`. Essentially you are removing this because it is\nhandled by a different service, `dnscrypt-proxy.socket`. \n\nNow to add your preferred DNS providers:\n\n-  `server_names = ['doh-eastas-pi-dns', 'doh.tiarap.org', 'quad9-dnscrypt-ipv4-filter-pri', 'quad9-doh-ipv4-filter-pri', 'doh-eastau-pi-dns', 'adguard-dns-doh']`\n\nThis allows for ad blocking DNS servers to be selected and deduced based on their ping. You could also just use regular DNS servers by using the following:\n\n-  `server_names = ['deffer-dns.au', 'publicarray-au', 'publicarray-au2', 'publicarray-au2-doh', 'publicarray-au-doh', 'cloudfare']`\n\nNow you're wondering where am I getting these DNS names from? Well you can make your own list from https://dnscrypt.info/public-servers/.\n\nThe rest of the recommended settings:\n\n-  `ipv4_servers = true`\n-  `ipv6_servers = false`\n-  `dnscrypt_servers = true`\n-  `doh_servers = true`\n-  `require_dnssec = true`\n-  `require_nolog = true`\n-  `require_nofilter = false`\n-  `fallback_resolvers = ['9.9.9.9:53', '8.8.8.8:53']`\n\nObviously these settings are not everything, but this is what I recommend you change/add from the default.\n\nNow download the relay and public resolvers files, because apparently DNSCrypt does not do it for you:\n-  `wget https://download.dnscrypt.info/dnscrypt-resolvers/v3/relays.md -P /etc/dnscrypt-proxy/`\n-  `wget https://download.dnscrypt.info/dnscrypt-resolvers/v3/public-resolvers.md -P /etc/dnscrypt-proxy/`\n\nNow you need to modify the aforementioned `dnscrypt-proxy.socket` service to point to the correct IP address, so run `sudo nano /lib/systemd/system/dnscrypt-proxy.socket`\nand modify `ListenStream` and `ListenDatagram` to be `0.0.0.0:53`. Having it at 0.0.0.0 rather than 127.0.0.1 means that wg0\nwill be able to access it. You can point your clients to use this DNS by changing their configuration to point to the DNS of 10.0.0.1.\n\nAt this stage  you need to modify your systems default resolve file, but first back it up  \nwith `cp /etc/resolv.conf /etc/resolv.conf.backup` then delete it and make a new one and \ninsert `nameserver 127.0.0.1` and `options edns0`. You are no longer using your default DNS!\n\nYour system will likely try and revert these settings so lock the file with \n`chattr +i /etc/resolv.conf`, note that the `-i` switch will unlock it. \nYou should also modify `/etc/systemd/resolved.conf` and uncomment or add\n`DNSStubListener=No` this may help prevent port clashing in the future.\n\nOnce this is all done, you should restart the service daemon with `systemctl daemon-reload`.\nNow you can restart the DNSCrypt service with `systemctl restart dnscrypt-proxy`.\n\nCheck if its running with `systemctl status dnscrypt-proxy`. If it all went well it should look like this:\n\n![](media/dnscryptgood.jpg)\n\nNow run `sudo dnscrypt-proxy -resolve google.com` if this succeeded you are good to go!\nIf it didn't you probably didn't listen to me when I said restart, so go ahead and `sudo reboot`.\n\nFeel free to make a final confirmation test of the DNS by running\n`nslookup -q=A whoami.akamai.net` and looking at the respondant IP, thats your DNS.\nOnce you have wireguard setup can also go to `www.dnsleaktest.com` on your client device to see which server/s you're using.\n\nDon't have nslookup? `sudo apt install dnstools`, you will likely need this in the future anyhow.\n\nAnother test you can do for the client side is to simply stop the DNSCrypt service via `systemctl stop dnscrypt-proxy.service` and `systemctl stop dnscrypt-proxy.socket`, if websites timeout and you can still access `https://1.1.1.1/` then all is well! Start it back up and continue!\n\n## WireGuard ##\n\nNow to finally install WireGuard, this is achieved by issuing `apt-get\ninstall wireguard`. Ensure the service is installed and running by\nissuing `modprobe wireguard` and `lsmod | grep wireguard`. \n\nFor the latter command you should see something along the lines of:\n-   `wireguard             225280  0`\n-   `ip6_udp_tunnel         16384  1 wireguard`\n-   `udp_tunnel             16384  1 wireguard`\n\nThe next step is to generate the key pair, but first change the permission of the\n`/etc/wireguard/` directory with `umask 077`. This will ensure that only\nthe owner is able to read or execute newly-created files. Now the actual\nkey generation, issue `wg genkey | tee privatekey | wg pubkey \u003e publickey`.\n\nFrom this point on you can cheat by going to https://wireguardconfig.com/ and\nusing a generated configuration. But is not that difficult to set it up yourself, \nstart with creating the following file `/etc/wireguard/wg0.conf` and adding your \nown private key and a client's public key to the following configuration in the \nimage below (It is best to do both the client and server steps at the same time). \nThen save it and modify its permissions with `chmod 600 /etc/wireguard/wg0.conf`. \n\nNow create the `wg0.conf`:\n\n-   `[Interface]`\n-   `PrivateKey = INSERT YOUR PRIVATE KEY HERE`\n-   `Address = 10.0.0.1/24`\n-   `SaveConfig = true`\n-   `PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE`\n-   `PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE`\n-   `ListenPort = 51820`\n\n-   `[Peer]`\n-   `PublicKey = INSERT CLIENT PUBLIC KEY HERE`\n-   `AllowedIPs = 10.0.0.2/32`\n\nSubsequent clients are  added below each other with the same formatting, to then remove a user you issue \n`wg set wg0 peer CLIENTPUBLICKEY remove` or modify the wg0.conf manually. To load a\nconfiguration (to add another client for example) without resetting the\nservice run `wg addconf wg0 \u003c(wg-quick strip wg0)`.\n\nNow ensure that your system can accommodate IP forwarding by editing\n`/etc/sysctl.conf` and adding `net.ipv4.ip_forward=1` and `net.ipv6.conf.all.forwarding=1`. \nOnce this is done run `sudo sysctl -p` to load your newly edited configuration. \nNow you can finally start WireGuard with `sudo wg-quick up wg0` and confirm its running with \n`wg show`.\n\n![](media/image19.jpeg)\n\nConnect to the VPS via WireGuard to finally confirm that you are indeed\npart of the server's LAN, this is important for a final security measure. If all is well make\nWireGuard start at boot with `systemctl enable wg-quick@wg0`. You can confirm that there is indeed\nencrypting traffic by issuing `tcpdump -n -X -I eth0 host YOURSERVERIP` \nand looking for WireGuard's magic header identifier in each packet `0400 0000`.\n\n![](media/image20.jpeg)\n\n### Windows Client Side Setup ###\n\nRunning the official WireGuard client for Windows, you are able to\ncreate a new tunnel with a few clicks. Within the client click on the\ndown arrow next to `Add Tunnel` and create a new tunnel. You will be\npresented with a form with part of a configuration along with a\npre-generated public and private key, as seen below.\n\n![](media/image21.png)\n\nUse this information to build your client configuration as per the\nsecond screenshot above. Once this is done, click `Activate` and you\nwill be connected!\n\n### Linux Client Side Setup ###\n\nFrom the client's perspective setting up WireGuard is very similar, it\nstarts with the following commands 'apt install wireguard resolvconf' to\ninstall the service and to ensure the DNS functionality, then to confirm\nits running run `lsmod | grep wireguard`. Now you have to generate a\nprivate and public key, the private key stays on your system and the\npublic key is given to the server so you can become a peer. This is done\nwith `wg genkey | tee privatekey | wg pubkey \u003e publickey`. Then\nchange the permission of the `/etc/wireguard/` directory with `umask\n077`. Create now your own WireGuard configuration file in\n`/etc/wireguard/wg0.conf` and insert the following.\n\n-   `[Interface]`\n-   `PrivateKey = CLIENT PRIVATE KEY`\n-   `ListenPort = 51820`\n-   `Address = 10.0.0.4/24`\n-   `DNS = 10.0.0.1`\n-   `[Peer]`\n-   `PublicKey = SERVER PUBLIC KEY`\n-   `AllowedIPs = 0.0.0.0/0, ::/0`\n-   `Endpoint = SERVERIP:51820`\n\nThe AllowedIPs setting can be changed to permit LAN access or can\nrestrict to a specific IP address. Once this is done change the\npermissions of the file with `chmod 600 /etc/wireguard/wg0.conf` and\nthen ensure that your system can accommodate IP forwarding by editing\n`/etc/sysctl.conf` and adding `net.ipv4.ip_forwarding=1` and\n`net.ipv6.conf.all.forwarding=1`. Now you can start the connection with\n`wg-quick up wg0` and confirm its running with `wg show` and finally, to\nensure it starts at boot run `systemctl enable wg-quick@wg0`.\n\n### Adding New People Post-Installation ###\n\nWell if you've figured it out by now new clients need a matching public and private key.\nThis can be generated by the server (or any linux machine running wireguard) with the command\n`wg genkey | tee privatekey | wg pubkey \u003e publickey`. If you're using the mobile app you can\ndo the same, just click `Create from Scratch` and in the interface section click the refresh arrows\nand it will generate your private and public key. Then fill out the interface name (whatever you wish)\nthe IP address of the server, its port, DNS server and MTU. Then you're done. On the server side the public \nkey must be added to your `wg0.conf`. So simply add another `[Peer]`, add their public key and assign their IP address.\n\nAnother way of doing this for mobile users is to generate the public and private keys for them and essentially create a configuration\nand place it into a QR code for them to read. Then you add the public key youve generated into the `wg0.conf` as above.\n\nFor Windows users it is the same, but you have to write out the client configuration from scratch, you surely know how to by know!\n\nOnce this is all done you need to refresh the configuration (albeit without resetting the interface) with the command\n`wg addconf wg0 \u003c(wg-quick strip wg0)`.\n\n## Additional Security Post Installation ##\n\n### SSH via WireGuard (With Knocking) ###\n\nPort knocking is great, but why allow anybody from any IP address to\nknock at all? Why not limit the knocks to those already on the WireGuard\nnetwork, this way you can ensure that only those you can trust can even\nbegin the knocking process. This is achieved by simply modifying the\nknockd configuration file, as per above, but changing the interface to wg0.\nThis is done by simply adding `interface = wg0` in the options section.\nIf you wanted to be even more paranoid, you could set up an additional\nWireGuard interface specifically to access SSH and use that as the\nknocking interface, this would allow sharing of the WireGuard VPN access\nbut also ensuring your own secure access on a different interface and IP\naddress, solely for SSH.\n\n### Connection Profiling ###\n\nWebsites detect your Maximum Transmission Units (MTU) and use that against you, this is a known method to fingerprint connections. Wireguard uses the default MTU of `1420` which is also the default of IPSec. So if a website does not allow VPN connections, this is their point of call. Now what would be your new MTU? It is important to get this value right. You can use websites like http://www.letmecheck.it/mtu-test.php to determine the best one for a particular website/service but I found that `1480` seems best. It will get fingerprinted as a IPIP/SIT tunnel, so a Linux virtual interface - which is better than IPSec. \n\nTo change the MTU on the fly you can simply run `sudo ifconfig wg0 mtu 1480 up`. Confirm it has been changed with `netstat -i` or with `ifconfig`. From here you can make the value permanent by adding it to the `wg0.conf` file by simply adding `MTU = 1480` within the interface section. Note you must change the MTU in your client also, else you will experience dropouts. \n\n![](media/image24.jpeg)\n\n### SSH Honeypot (Optional Learning/Investigative Tool) ###\n\nI decided to install a medium interaction SSH honeypot as this service\nwill likely be a target for hackers and I was curious to see the\npasswords used and simply the amount of attacks I would get on a daily\nbasis. Now doing this will open a false SSH port, given that the real\none is on port 88 and only accessible through WireGuard this is actually\nquite safe to run. There were a lot of prerequisites to install prior to\nthe actual honeypot and these were as follows:\n\n-   `sudo apt-get install python-minimal`\n\n-   `sudo apt-get install python-pip`\n\n-   `sudo apt-get install build-essential`\n\n-   `sudo apt-get install default-jre`\n\n-   `sudo pip install --upgrade pip`\n\n-   `sudo pip install setuptools`\n\n-   `sudo pip install pyasn1 pyasn1-modules`\n\n-   `sudo pip install virtualenv`\n\n-   `sudo pip install pycrypto`\n\n-   `sudo pip install virtualenv`\n\n-   `sudo pip install twisted`\n\n-   `sudo pip install cryptography`\n\n-   `sudo pip install tzlocal`\n\n-   `sudo pip install bcrypt`\n\nOnce this was done I cloned the git repository of XSweet, the SSH\nHoneypot. This was done with the command `git clone https://github.com/techouss/xsweet.git`.\nI did this within the home directory as I felt this would be an adequate\nlocation, given this is also where I installed DNSCrypt. Now to run this\non port 22 I had to open it along with port 2222, the actual port that\nthe honeypot will be running on. I then had to forward 22 to 2222 to\nensure that the honeypot would function. This was done with the\nfollowing commands:\n\n-   `sudo iptables -A PREROUTING -t nat -p tcp --dport 22 -j REDIRECT --to-port 2222`\n\n-   `sudo iptables -A INPUT -p tcp --dport 2222 -j ACCEPT`\n\n-   `sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT`\n\nI tested its functionality by running it with `python xsweet.py` and\nopening an SSH connection on port 22 to my server. It indeed functioned,\nbut I could not keep it running this way as it would consume the\nsession. I had to run it in the background and so to do this I ensured\nthat the `xsweet.py` file was an executable by issuing the command\n`chmod +x xsweet.py`. I then made it run in the background by issuing\nthe command `nohup python /xsweet/xsweet.py \u0026`, to confirm it was\nrunning I ran `ps aux | grep xsweet` and tested the connection to the\nfake SSH again.\n\n![](media/image25.jpeg)\n\nIn the above screenshot you can see a list of all the failed username\nand password's which were attempted against the honeypot. These are\nstored within a `victims` folder along with stored sessions.\n\n![](media/image26.jpeg)\n\nIn this screenshot above you can see how the fake SSH session allows for\ninteraction and false outputs, of which are recorded. This would also\ninclude files that are uploaded/downloaded to the server, this way you\ncan forensically examine potential malware/payloads etc.\n\n## Other Considerations ##\n\nYou must be aware of the Autonomous System Number (ASN) that is assigned\nto your server IP address when you buy your VPS. Mine for example is\nAS16276, belonging to OVH SAS in Canada, its purpose is for paid VPN,\nhosting and 'good' bots. It has however 40,382 active spam IP addresses\nout of a total of 381,412 -- that's 10.5% of the entire network\nconsisting of spammers, this is not good and was likely the reason\nbehind having multiple DDoS attacks when my IP was still new.\n\n![](media/image27.jpeg)\n\nWhat this means is that should you indeed use your server as a VPN for\ndaily use, you may find that you have been banned from websites you have\nnever visited, this is simply because the website has chosen to ban not\nyour IP address but your ASN entirely. Luckily the IP address I have is\nunique to my account and is not shared, this situation would be worse on\na commercial VPN provider, where allocated shared IPs can be banned in\nglobal black lists due to spamming and other illegal activity. My ASN is\nalso not part of the Spamhaus Project ASN-DROP list; if it were then I\nwould certainly not continue using my hosting provider.\n\n![](media/1005.png)\n\nYour ASN could easily just be banned from websites you're trying to visit, this is though more common with public VPN's as their anonymity allows for abuse and thus for a service to block one IP would be meaningless, so they ban the entire VPN provider, or at least a large range of their servers.\n\n### Logs ###\nI highly suggest installing `lnav` for log aggregation. But prior to doing this remember\nto change your time-zone with `sudo timedatectl set-timezone your_time_zone`.\n\nIf for some reason you do not want logs I suggest running the following commands\nor at least setting them up to run on a schedule in the background (see Cron Jobs):\n\n-   `cat /dev/null \u003e ~/.bash_history`\n-   `for logs in ``find /var/log -type f``; do \u003e $logs; done`\n-   `sudo service rsyslog restart`\n\n### Cron Jobs ###\nCron jobs are tasks that can be set automatically by the system. One that we can make that\nis relevant to this project is the apparent need to make the knockd service restart itself\nafter the system reboots (due to wireguard starting too late) and fixing the wg0 interface MTU.\n\nFor this example start with creating a simple bash script, `nano hello.sh`.\n\n-   `#!/bin/bash`\n-   `logger \"=== Boot Sequence Quick-Fix ===\"`\n-   `sudo wg-quick up wg0`\n-   `sudo ifconfig wg0 mtu 1480 up`\n-   `sudo sysctl net.ipv4.ip_default_ttl=30`\n-   `sudo systemctl restart dnscrypt-proxy`\n-   `sudo systemctl restart knockd.service`\n-   `logger \"=== Quick-Fix is Done! ===\"`\n\nNow just save the file and change its attribute to executable with `chmod 700 hello.sh`.\nTo have your script run when the system starts up you have to open the crontab editor.\nDo this with `crontab -e`, it will prompt you to choose an editor, go with nano, or option 1.\nWithin this page type in `@reboot sleep 60 \u0026\u0026 /home/wherever/your/script/is/hello.sh`.\nSave and close. \n\nNow you have to enable the cron service with `systemctl enable cron.service`.\nYou can see your user cron jobs with `crontab -l` and you can see the history of your cronjobs \nwith `systemctl status cron.service` or ideally `sudo grep CRON /var/log/syslog`. And thats that!\n\nBe careful with what you put in these scripts, because they are run as root (depending on your permissions) they are very powerful.\n\n## Tunneling aka VPN Chain aka Double-VPN ##\n\nOK, so you're confident with this guide and you want to step it up a bit? You want to connect through two VPNs before accessing the internet?\nWell first step is to literally do this guide TWICE, it's surely not that hard at this point, right?\n\nNow you have two VPS servers we will call them VPS1 and VPS2, the first is what you will connect to, the second is what ultimately will be your external IP.\nThus it will be: `You ---\u003e VPS1 ---\u003e VPS2 ---\u003e Internet`.\n\nOn VPS1, create a second wireguard interface, `wg1` and generate a new set of public and private keys with `wg genkey | tee privatekey | wg pubkey \u003e publickey`. \nYou do this by making `nano /etc/wireguard/wg1.conf`. Within this interface file insert the following (Note, the IP address does not have to be on a different subnet, remember, this interface is essentially just another client):\n\n-   `[Interface]`\n-   `Address = 10.0.0.4/24`\n-   `PrivateKey = theprivatekeyyoujustmade`\n-   `FwMark = 51280`\n\n-   `[Peer]`\n-   `PublicKey = thepublickeyofVPS2`\n-   `AllowedIPS = 0.0.0.0/0`\n-   `Endpoint = VPS2IPAddress:51820`\n-   `PersistentKeepalive = 21`\n\nNow edit your VPS1 `wg0` configuration file and add `FwMark = 51820` much like `wg1` has. Save and close, VPS1 configuation complete!\n\nNow you must add these routes using the following commands:\n\n-   `echo \"1 wg1\" \u003e\u003e /etc/iproute2/rt_tables`\n-   `ip route add 0.0.0.0/0 dev wg0 table wg1`\n-   `ip rule add from 10.0.0.0/24 lookup wg1`\n\nNow go into your VPS2 and edit its `wg0` file and add a new peer using VPS1's public key (that you made earlier) and give it the IP address of `10.0.0.4/32` (or whatever matches the configuration you just made).\n\nRestart VPS2's `wg0` either fully with `wg-quick down wg0` and then `wg-quick up wg0` or just simply run `wg addconf wg0 \u003c(wg-quick strip wg0)`.\nVPS2 will now be ready to recieve VPS1, so go back into VPS1 and do the same thing to its `wg0`. At this point you can finally start `wg1`.\n\nIf all went well VPS1's external IP address will now be that of VPS2. Try it out with `curl whatismyip.akamai.com`.\n\nThe client can now connect to VPS1, which will connect through VPS2! Mission Complete! You can also obviously connect to either of them individually still.\nDisabling `wg1` on VPS1 will not cause any issue, the connection will just be as it was before. So you can essentially turn this ability on and off at your will.\n\nOn the topic of turning it on and off at your will, here is a nice and clever method that does not involve you logging into SSH. Just use the `knockd` service!\nStart by editing `/etc/knockd.conf` and adding another item much like how SSH is done, check out this example - note that each and every port is different, if you use the same port the sequence will get broken and it wont work. Don't forget to restart the service when you're finished editing the config file, you can do that with `systemctl restart knockd.service`.\n\n![](media/wg1knockdconf.png)\n\nBasically `knockd` can do more than just enable and disable your SSH port, you can make it do whatever command you wish, so why not use it to toggle your double-vpn!\nOnce the ports are knocked you can see in the log `/var/log/knockd.log` the sequence that it did and the command it ran. You can use your imagination for what other scripts or commands you could run.\n\n![](media/wg1knockd.png)\n\n## Troubleshooting ##\n\nDuring my time with this setup I have found and discovered various small issues, \nhere are my quick fixes for them.\n\n### Unable to Locate Package: Wireguard? ###\n\nAdd these to the bottom of your `/etc/apt/sources.list`\n\n-   `deb  http://deb.debian.org/debian  stretch main`\n-   `deb-src  http://deb.debian.org/debian  stretch main`\n-   `deb http://ftp.debian.org/debian buster-backports main`\n-   `deb-src http://ftp.debian.org/debian buster-backports main`\n\nThen run `apt update`.\n\n### Wireguard Cannot Compile ###\n\nIn `/usr/src/wireguard-1.0.20200623/socket.c` add these two lines after the #include's:\n\n-   `#undef ipv6_dst_lookup_flow`\n-   `#define ipv6_dst_lookup_flow(a, b, c, d) ipv6_dst_lookup(a, b, \u0026dst, c) + (void *)0 ?: dst`\n\nNow as root run `/usr/lib/dkms/dkms_autoinstaller start`\n\nIf this does not work read the following and follow it `https://www.wireguard.com/compilation/`\n\nNow remove lines 95, 96, 97 and 99 from `compat.h`\nCompile and install as per the official guide\n\n### Wireguard Won't Start ###\n\n![](media/wgfail.png)\n\nIf you're getting an error like `RTNETLINK Operation Not Supported` when trying to start `wg-quick up wg0` \nyou need to input `sudo modprobe wireguard`. If the resultant answer is something along the lines of \n`Badprobe: FATAL: Module wireguard not found in directory ...`  then your solution is to run \n`apt-get install wireguard-dkms wireguard-tools linux-headers-$(uname -r)`.\n\n### Knockd Not Opening Port ###\n\nWell if you've not modified the interface for knockd, it could simply be because you're on the VPN.\nIts default settings are to accept knocks from eth0, if you're on the VPN you're on wg0. It won't work.\nIf it works when you disconnect from the VPN you should add the wg0 interface into knockd if you prefer accessing it this way.\n\n### Knockd Not Starting at Boot ###\n\nConfirm the issue with `systemctl is-enabled knockd.service`, if it comes up as `static`\nthen edit `/lib/systemd/system/knockd.service` and add this to the bottom:\n\n-   `[Install]`\n-   `WantedBy=multi-user.target`\n-   `Alias=knockd.service`\n\nRun the following: `systemctl enable knockd.service` and `systemctl is-enabled knockd.service`\nit should now come up as `enabled`.\n\nIt may still not start due to the sequence of how things start up, so it may error out saying\nthat there is no wg0 interface. If this is the case you need to make a cron job that restarts it\nafter wireguard starts.\n\n### DNSCrypt Not Starting at Boot (Or at all) ###\nConfirm if port 53 is not already in use by something else with `lsof -i -P -n | grep LISTEN`\nKill the PID of whatever is already using that port.\nIf it is Avahi you can disable it from booting with the following commands:\n\n-   `systemctl stop avahi-daemon.socket`\n-   `systemctl stop asystemvahi-daemon.service`\n-   `systemctl disable avahi-daemon`\n\nStill not working? \nIf it says `can't bind socket` or `could not open ports` try running `netstat -patuln | grep 53`.\nIf you see `1/init` using port 53 then you need to run `systemctl stop dnscrypt-proxy.socket`\nand then restart dnscrypt again. This should fix it.\n\nStill not working? Well I guess systemd is using port 53. You can disable it by running\n`systemctl stop systemd-resolved` and `systemctl disable systemd-resolved`.\nYou don't really need it given you're using DNSCrypt.\n\n### Some Websites Timeout/Cannot Resolve After Reboot ###\nIf you have changed the MTU it likely went back to the default and thus your client side\nsettings are not matching, causing dropouts.\n\nIf this is not the issue change the wg0 MTU to `1480`.\nAgain, ensure that your client matches the MTU settings of the wg0 interface.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbetterwayelectronics%2Fsecure-wireguard-implementation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbetterwayelectronics%2Fsecure-wireguard-implementation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbetterwayelectronics%2Fsecure-wireguard-implementation/lists"}