Skip to content

Latest commit

History

140 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

IKEv2-setup

Table of contents

What?

A Bash script that takes Ubuntu Server 20.04 LTS or 18.04 LTS from clean install to production-ready IKEv2 VPN with strongSwan. Comments and pull requests welcome. It may still work on 17.10, 17.04 or 16.10 if you remove the version check, but these are not tested.

VPN server

  • The VPN server identifies itself with a Let's Encrypt certificate, so there's no need for clients to install private certificates — they can simply authenticate with username and strong password (EAP-MSCHAPv2).

  • The only cipher set implemented is CNSA/RFC 6379 Suite B with confidentiality/encryption.

  • The box is firewalled with iptables and configured for unattended security upgrades, and the Let's Encrypt certificate is set up to auto-renew, so it could be safe to forget about it all until 18.04 reaches end-of-life in 2023. (Note that iptables setup includes basic rate-limiting, dropping new connections if there have been 60+ connection attempts in the last 5 minutes).

VPN clients

The VPN is tested working with:

  • macOS 10.12 – 10.15, iOS 10 – 13 — Built-in clients. A .mobileconfig profile is generated for Mac and iOS, to set up secure ciphers and enable Connect on demand support.
  • Windows 10 Pro — Built-in client. PowerShell commands are generated to configure the VPN and secure ciphers.
  • Ubuntu (17.04 and presumably others) — Using strongSwan. A Bash script is generated to set this up.
  • Android — Using the official strongSwan app.

Configuration files, scripts and instructions are sent by email. They are also dropped in the newly-created non-root user's home directory on the server (this point may be important, because VPS providers sometimes block traffic on port 25 by default and, even if successfully sent, conscientious email hosts will sometimes mark the email as spam).

Caveats

  • There's no IPv6 support — and, in fact, IPv6 networking is disabled — because supporting IPv6 prevents the use of forceencaps, and honestly also because I haven't got to grips with the security implications (ip6tables rules and so on).
  • The script won't work as-is on 16.04 LTS because the certbot package is outdated, found under the name letsencrypt, and doesn't renew certificates automatically.
  • Don't use this unmodified on a server you use for anything else: it does as it sees fit with various wider settings that may conflict with what you're doing.

How?

  1. Pick a domain name for the VPN server and ensure that it already resolves to the correct IP by creating the appropriate A record in the DNS and making sure it has propagated. Let's Encrypt needs this in order to create your server certificate.

Don't want to use your own domain name here? You could try using the reverse DNS name provided by your server host, or an automatic IP/DNS alias service such as sslip.io, xip.io, nip.io, s.test.cab, or xip.lhjmmc.cn (earlier versions of this script used an sslip.io address by default). However, both of these options may fall foul of Let's Encrypt's per-domain rate limit of 50 certificates per week. Note that ephemeral AWS domain names like ec2-34-267-212-76.compute-1.amazonaws.comare not accepted by Let's Encrypt.

  1. Start with a clean Ubuntu 20.04 or 18.04 Server installation. The cheapest VPSs offered by Linode, OVH, vps.ag, Google, Hetzner and Vultr, and Scaleway's ARM64-2GB, have all been tested working. On Scaleway, unblock SMTP ports in the admin panel and hard reboot the server first, or your configuration email will not be delivered. On Vultr, port 25 may also be blocked, but you won't know, and the only way to fix it is to open a support ticket.

  2. Optionally, set up key-based SSH authentication (alternatively, this may have been handled automatically by your server provider, or you may choose to stick with password-based authentication). This may require you to run some or all of the following commands, with appropriate substitutions, on the machine you're going to be logging in from:

    ssh-keygen -t ed25519 -C "me@my-domain.tld" # if you need a new key, ed25519 is the latest and possibly most secure option
    ssh-keygen -t rsa -b 4096 -C "me@my-domain.tld" # alternatively, use RSA and go (4,096 bits) large
    ssh root@myvpn.example.net # if your host forces a password change before anything else (e.g. Hetzner), do it now, then exit
    ssh-copy-id -i ~/.ssh/id_ed25519 root@myvpn.example.net # copy your public key over to the VPN server
    ssh root@myvpn.example.net # log back in to the server for the next step ...
    
  3. On your new server installation, become root, download the script, give it execute permissions, and run it:

    wget https://raw.githubusercontent.com/jawj/IKEv2-setup/master/setup.sh
    chmod u+x setup.sh
    ./setup.sh
    
  4. You'll be prompted to enter all the necessary details after the software updates and installations complete. If you are not using key-based SSH authentication, you must pick a really strong password for the login user when prompted, or your server will be compromised.

    The part of your session where the script asks you questions should look something like this:

     --- Configuration: VPN settings ---
    Network interface: eth0
    External IP: 100.100.100.100
    ** Note: hostname must resolve to this machine already, to enable Let's Encrypt certificate setup **
    Hostname for VPN: VPN username: george
    VPN password (no quotes, please): Confirm VPN password: Public DNS servers include:
    176.103.130.130,176.103.130.131 AdGuard https://adguard.com/en/adguard-dns/overview.html
    176.103.130.132,176.103.130.134 AdGuard Family https://adguard.com/en/adguard-dns/overview.html
    1.1.1.1,1.0.0.1 Cloudflare/APNIC https://1.1.1.1
    84.200.69.80,84.200.70.40 DNS.WATCH https://dns.watch
    8.8.8.8,8.8.4.4 Google https://developers.google.com/speed/public-dns/
    208.67.222.222,208.67.220.220 OpenDNS https://www.opendns.com
    208.67.222.123,208.67.220.123 OpenDNS FamilyShield https://www.opendns.com
    9.9.9.9,149.112.112.112 Quad9 https://quad9.net
    77.88.8.8,77.88.8.1 Yandex https://dns.yandex.com
    77.88.8.88,77.88.8.2 Yandex Safe https://dns.yandex.com
    77.88.8.7,77.88.8.3 Yandex Family https://dns.yandex.com
    DNS servers for VPN users (default: 1.1.1.1,1.0.0.1): 176.103.130.130,176.103.130.131
    --- Configuration: general server settings ---
    Timezone (default: Europe/London): Email address for sysadmin (e.g. j.bloggs@example.com): me@my-domain.tld
    Desired SSH log-in port (default: 22): 2222
    New SSH log-in user name: george
    Copy /root/.ssh/authorized_keys to new user and disable SSH password log-in [Y/n]? y
    New SSH user's password (e.g. for sudo): Confirm new SSH user's password: 
  5. Once you're up and running, use these commands for some insight into what's going on:

     sudo ipsec statusall # status, who's connected, etc.
    sudo iptables -L -v # how much traffic has been forwarded, dropped, etc.?
    sudo tail -f /var/log/syslog # real-time logs of (dis)connections etc.
    

Troubleshooting

If things don't work out right away ...

  • On the client: make sure you created the connection using the newly emailed .mobileconfig file or PowerShell commands. Setting it up manually via the OS GUI will not work, since it will default to insecure ciphers which the server has not been configured to support. Also note that .mobileconfig files generated with earlier iterations of this script may no longer be compatible, since the configured ciphers have changed from time to time.

  • On the server: check that network ingress for UDP on ports 500 and 4500 is enabled (on some cloud platforms you'll have to add appropriate firewall rules to your virtual network). Also check that packet forwarding is enabled (on some cloud platforms this is controlled by a configuration setting that's off by default).

  • Check the server logs on strongSwan startup and when you try to connect, and the client logs when you try to connect.

    • On the server: Log in via SSH, then sudo tail -f /var/log/syslog. To see startup logs, log in to another session and sudo ipsec restart there, then switch back. To see what's logged during a connection attempt, try to connect from a client.

    • On the client: On a Mac, open Console.app in /Applications/Utilities. If connecting from an iPhone, plug the iPhone into the Mac. Pick the relevant device (in the bar down the left), filter the output (in the box at top right) to nesession, and try to connect. (On Windows or Linux I don't know where you find the logs — if you know, feel free to write the explanation and send a pull request).

  • The setup script is now more or less idempotent — you should be able to run it repeatedly with no ill effects — so, when you've fixed any issues, simply run it again.

  • If you have a tricky question about strongSwan, it's probably better to raise it with the strongSwan team than file an issue here.

Users

To add or change VPN users, it's:

 sudo nano /etc/ipsec.secrets

Edit usernames and passwords as you see fit (but don't touch the first line, which specifies the server certificate). The line format for each user is:

 someusername : EAP "somepassword"

To exit nano it's Ctrl + O then Ctrl + X, and to have strongSwan pick up the changes it's:

 sudo ipsec secrets

Upgrades

If you're on a pre-18.04 version of Ubuntu, it's probably easiest to make a record of any changes to ipsec.secrets, blow the whole thing away and reinstall, then reinstate ipsec.secrets.

Note that you may also need to delete and recreate all your client connection settings using the updated PowerShell commands or .mobileconfig file, since there have been a few cipher changes over time.

Bonus paranoia

Your traffic is not logged on the server, but if you're feeling especially paranoid there are various things you could do to reduce logging further. A simple and somewhat drastic option (once you've got everything working) is:

 sudo rm /var/log/syslog && sudo ln -s /dev/null /var/log/syslog
sudo rm /var/log/auth.log && sudo ln -s /dev/null /var/log/auth.log

Why?

We use a similar setup as a corporate VPN at PSYT. And I use this to bounce my personal web browsing via Europe, in the hope of giving Theresa May's Investigatory Powers Bill the finger.

Why IKEv2?

  • Fair security
  • Built-in clients for latest iOS, Mac and Windows (+ trustworthy free install on Android)
  • Connect on demand support on iOS and Mac
  • Robust to connection switching and interruptions via MOBIKE

More on IKEv2 at https://www.cl.cam.ac.uk/~mas90/resources/strongswan/ and https://www.bestvpn.com/blog/4147/pptp-vs-l2tp-vs-openvpn-vs-sstp-vs-ikev2/

Why not Algo?

Feel free to use Algo instead. It has similar aims, and now configures WireGuard too. However, it has many more moving parts, and requires several local installation steps before you even start setting up your VPN. This script is intended to be much simpler.

About

Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - devops35/IKEv2-setup: Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server · GitHub
Skip to content

Latest commit

History

140 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

IKEv2-setup

Table of contents

What?

A Bash script that takes Ubuntu Server 20.04 LTS or 18.04 LTS from clean install to production-ready IKEv2 VPN with strongSwan. Comments and pull requests welcome. It may still work on 17.10, 17.04 or 16.10 if you remove the version check, but these are not tested.

VPN server

  • The VPN server identifies itself with a Let's Encrypt certificate, so there's no need for clients to install private certificates — they can simply authenticate with username and strong password (EAP-MSCHAPv2).

  • The only cipher set implemented is CNSA/RFC 6379 Suite B with confidentiality/encryption.

  • The box is firewalled with iptables and configured for unattended security upgrades, and the Let's Encrypt certificate is set up to auto-renew, so it could be safe to forget about it all until 18.04 reaches end-of-life in 2023. (Note that iptables setup includes basic rate-limiting, dropping new connections if there have been 60+ connection attempts in the last 5 minutes).

VPN clients

The VPN is tested working with:

  • macOS 10.12 – 10.15, iOS 10 – 13 — Built-in clients. A .mobileconfig profile is generated for Mac and iOS, to set up secure ciphers and enable Connect on demand support.
  • Windows 10 Pro — Built-in client. PowerShell commands are generated to configure the VPN and secure ciphers.
  • Ubuntu (17.04 and presumably others) — Using strongSwan. A Bash script is generated to set this up.
  • Android — Using the official strongSwan app.

Configuration files, scripts and instructions are sent by email. They are also dropped in the newly-created non-root user's home directory on the server (this point may be important, because VPS providers sometimes block traffic on port 25 by default and, even if successfully sent, conscientious email hosts will sometimes mark the email as spam).

Caveats

  • There's no IPv6 support — and, in fact, IPv6 networking is disabled — because supporting IPv6 prevents the use of forceencaps, and honestly also because I haven't got to grips with the security implications (ip6tables rules and so on).
  • The script won't work as-is on 16.04 LTS because the certbot package is outdated, found under the name letsencrypt, and doesn't renew certificates automatically.
  • Don't use this unmodified on a server you use for anything else: it does as it sees fit with various wider settings that may conflict with what you're doing.

How?

  1. Pick a domain name for the VPN server and ensure that it already resolves to the correct IP by creating the appropriate A record in the DNS and making sure it has propagated. Let's Encrypt needs this in order to create your server certificate.

Don't want to use your own domain name here? You could try using the reverse DNS name provided by your server host, or an automatic IP/DNS alias service such as sslip.io, xip.io, nip.io, s.test.cab, or xip.lhjmmc.cn (earlier versions of this script used an sslip.io address by default). However, both of these options may fall foul of Let's Encrypt's per-domain rate limit of 50 certificates per week. Note that ephemeral AWS domain names like ec2-34-267-212-76.compute-1.amazonaws.comare not accepted by Let's Encrypt.

  1. Start with a clean Ubuntu 20.04 or 18.04 Server installation. The cheapest VPSs offered by Linode, OVH, vps.ag, Google, Hetzner and Vultr, and Scaleway's ARM64-2GB, have all been tested working. On Scaleway, unblock SMTP ports in the admin panel and hard reboot the server first, or your configuration email will not be delivered. On Vultr, port 25 may also be blocked, but you won't know, and the only way to fix it is to open a support ticket.

  2. Optionally, set up key-based SSH authentication (alternatively, this may have been handled automatically by your server provider, or you may choose to stick with password-based authentication). This may require you to run some or all of the following commands, with appropriate substitutions, on the machine you're going to be logging in from:

    ssh-keygen -t ed25519 -C "me@my-domain.tld" # if you need a new key, ed25519 is the latest and possibly most secure option
    ssh-keygen -t rsa -b 4096 -C "me@my-domain.tld" # alternatively, use RSA and go (4,096 bits) large
    ssh root@myvpn.example.net # if your host forces a password change before anything else (e.g. Hetzner), do it now, then exit
    ssh-copy-id -i ~/.ssh/id_ed25519 root@myvpn.example.net # copy your public key over to the VPN server
    ssh root@myvpn.example.net # log back in to the server for the next step ...
    
  3. On your new server installation, become root, download the script, give it execute permissions, and run it:

    wget https://raw.githubusercontent.com/jawj/IKEv2-setup/master/setup.sh
    chmod u+x setup.sh
    ./setup.sh
    
  4. You'll be prompted to enter all the necessary details after the software updates and installations complete. If you are not using key-based SSH authentication, you must pick a really strong password for the login user when prompted, or your server will be compromised.

    The part of your session where the script asks you questions should look something like this:

     --- Configuration: VPN settings ---
    Network interface: eth0
    External IP: 100.100.100.100
    ** Note: hostname must resolve to this machine already, to enable Let's Encrypt certificate setup **
    Hostname for VPN: VPN username: george
    VPN password (no quotes, please): Confirm VPN password: Public DNS servers include:
    176.103.130.130,176.103.130.131 AdGuard https://adguard.com/en/adguard-dns/overview.html
    176.103.130.132,176.103.130.134 AdGuard Family https://adguard.com/en/adguard-dns/overview.html
    1.1.1.1,1.0.0.1 Cloudflare/APNIC https://1.1.1.1
    84.200.69.80,84.200.70.40 DNS.WATCH https://dns.watch
    8.8.8.8,8.8.4.4 Google https://developers.google.com/speed/public-dns/
    208.67.222.222,208.67.220.220 OpenDNS https://www.opendns.com
    208.67.222.123,208.67.220.123 OpenDNS FamilyShield https://www.opendns.com
    9.9.9.9,149.112.112.112 Quad9 https://quad9.net
    77.88.8.8,77.88.8.1 Yandex https://dns.yandex.com
    77.88.8.88,77.88.8.2 Yandex Safe https://dns.yandex.com
    77.88.8.7,77.88.8.3 Yandex Family https://dns.yandex.com
    DNS servers for VPN users (default: 1.1.1.1,1.0.0.1): 176.103.130.130,176.103.130.131
    --- Configuration: general server settings ---
    Timezone (default: Europe/London): Email address for sysadmin (e.g. j.bloggs@example.com): me@my-domain.tld
    Desired SSH log-in port (default: 22): 2222
    New SSH log-in user name: george
    Copy /root/.ssh/authorized_keys to new user and disable SSH password log-in [Y/n]? y
    New SSH user's password (e.g. for sudo): Confirm new SSH user's password: 
  5. Once you're up and running, use these commands for some insight into what's going on:

     sudo ipsec statusall # status, who's connected, etc.
    sudo iptables -L -v # how much traffic has been forwarded, dropped, etc.?
    sudo tail -f /var/log/syslog # real-time logs of (dis)connections etc.
    

Troubleshooting

If things don't work out right away ...

  • On the client: make sure you created the connection using the newly emailed .mobileconfig file or PowerShell commands. Setting it up manually via the OS GUI will not work, since it will default to insecure ciphers which the server has not been configured to support. Also note that .mobileconfig files generated with earlier iterations of this script may no longer be compatible, since the configured ciphers have changed from time to time.

  • On the server: check that network ingress for UDP on ports 500 and 4500 is enabled (on some cloud platforms you'll have to add appropriate firewall rules to your virtual network). Also check that packet forwarding is enabled (on some cloud platforms this is controlled by a configuration setting that's off by default).

  • Check the server logs on strongSwan startup and when you try to connect, and the client logs when you try to connect.

    • On the server: Log in via SSH, then sudo tail -f /var/log/syslog. To see startup logs, log in to another session and sudo ipsec restart there, then switch back. To see what's logged during a connection attempt, try to connect from a client.

    • On the client: On a Mac, open Console.app in /Applications/Utilities. If connecting from an iPhone, plug the iPhone into the Mac. Pick the relevant device (in the bar down the left), filter the output (in the box at top right) to nesession, and try to connect. (On Windows or Linux I don't know where you find the logs — if you know, feel free to write the explanation and send a pull request).

  • The setup script is now more or less idempotent — you should be able to run it repeatedly with no ill effects — so, when you've fixed any issues, simply run it again.

  • If you have a tricky question about strongSwan, it's probably better to raise it with the strongSwan team than file an issue here.

Users

To add or change VPN users, it's:

 sudo nano /etc/ipsec.secrets

Edit usernames and passwords as you see fit (but don't touch the first line, which specifies the server certificate). The line format for each user is:

 someusername : EAP "somepassword"

To exit nano it's Ctrl + O then Ctrl + X, and to have strongSwan pick up the changes it's:

 sudo ipsec secrets

Upgrades

If you're on a pre-18.04 version of Ubuntu, it's probably easiest to make a record of any changes to ipsec.secrets, blow the whole thing away and reinstall, then reinstate ipsec.secrets.

Note that you may also need to delete and recreate all your client connection settings using the updated PowerShell commands or .mobileconfig file, since there have been a few cipher changes over time.

Bonus paranoia

Your traffic is not logged on the server, but if you're feeling especially paranoid there are various things you could do to reduce logging further. A simple and somewhat drastic option (once you've got everything working) is:

 sudo rm /var/log/syslog && sudo ln -s /dev/null /var/log/syslog
sudo rm /var/log/auth.log && sudo ln -s /dev/null /var/log/auth.log

Why?

We use a similar setup as a corporate VPN at PSYT. And I use this to bounce my personal web browsing via Europe, in the hope of giving Theresa May's Investigatory Powers Bill the finger.

Why IKEv2?

  • Fair security
  • Built-in clients for latest iOS, Mac and Windows (+ trustworthy free install on Android)
  • Connect on demand support on iOS and Mac
  • Robust to connection switching and interruptions via MOBIKE

More on IKEv2 at https://www.cl.cam.ac.uk/~mas90/resources/strongswan/ and https://www.bestvpn.com/blog/4147/pptp-vs-l2tp-vs-openvpn-vs-sstp-vs-ikev2/

Why not Algo?

Feel free to use Algo instead. It has similar aims, and now configures WireGuard too. However, it has many more moving parts, and requires several local installation steps before you even start setting up your VPN. This script is intended to be much simpler.

About

Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - devops35/IKEv2-setup: Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server · GitHub
Skip to content

Latest commit

History

140 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

IKEv2-setup

Table of contents

What?

A Bash script that takes Ubuntu Server 20.04 LTS or 18.04 LTS from clean install to production-ready IKEv2 VPN with strongSwan. Comments and pull requests welcome. It may still work on 17.10, 17.04 or 16.10 if you remove the version check, but these are not tested.

VPN server

  • The VPN server identifies itself with a Let's Encrypt certificate, so there's no need for clients to install private certificates — they can simply authenticate with username and strong password (EAP-MSCHAPv2).

  • The only cipher set implemented is CNSA/RFC 6379 Suite B with confidentiality/encryption.

  • The box is firewalled with iptables and configured for unattended security upgrades, and the Let's Encrypt certificate is set up to auto-renew, so it could be safe to forget about it all until 18.04 reaches end-of-life in 2023. (Note that iptables setup includes basic rate-limiting, dropping new connections if there have been 60+ connection attempts in the last 5 minutes).

VPN clients

The VPN is tested working with:

  • macOS 10.12 – 10.15, iOS 10 – 13 — Built-in clients. A .mobileconfig profile is generated for Mac and iOS, to set up secure ciphers and enable Connect on demand support.
  • Windows 10 Pro — Built-in client. PowerShell commands are generated to configure the VPN and secure ciphers.
  • Ubuntu (17.04 and presumably others) — Using strongSwan. A Bash script is generated to set this up.
  • Android — Using the official strongSwan app.

Configuration files, scripts and instructions are sent by email. They are also dropped in the newly-created non-root user's home directory on the server (this point may be important, because VPS providers sometimes block traffic on port 25 by default and, even if successfully sent, conscientious email hosts will sometimes mark the email as spam).

Caveats

  • There's no IPv6 support — and, in fact, IPv6 networking is disabled — because supporting IPv6 prevents the use of forceencaps, and honestly also because I haven't got to grips with the security implications (ip6tables rules and so on).
  • The script won't work as-is on 16.04 LTS because the certbot package is outdated, found under the name letsencrypt, and doesn't renew certificates automatically.
  • Don't use this unmodified on a server you use for anything else: it does as it sees fit with various wider settings that may conflict with what you're doing.

How?

  1. Pick a domain name for the VPN server and ensure that it already resolves to the correct IP by creating the appropriate A record in the DNS and making sure it has propagated. Let's Encrypt needs this in order to create your server certificate.

Don't want to use your own domain name here? You could try using the reverse DNS name provided by your server host, or an automatic IP/DNS alias service such as sslip.io, xip.io, nip.io, s.test.cab, or xip.lhjmmc.cn (earlier versions of this script used an sslip.io address by default). However, both of these options may fall foul of Let's Encrypt's per-domain rate limit of 50 certificates per week. Note that ephemeral AWS domain names like ec2-34-267-212-76.compute-1.amazonaws.comare not accepted by Let's Encrypt.

  1. Start with a clean Ubuntu 20.04 or 18.04 Server installation. The cheapest VPSs offered by Linode, OVH, vps.ag, Google, Hetzner and Vultr, and Scaleway's ARM64-2GB, have all been tested working. On Scaleway, unblock SMTP ports in the admin panel and hard reboot the server first, or your configuration email will not be delivered. On Vultr, port 25 may also be blocked, but you won't know, and the only way to fix it is to open a support ticket.

  2. Optionally, set up key-based SSH authentication (alternatively, this may have been handled automatically by your server provider, or you may choose to stick with password-based authentication). This may require you to run some or all of the following commands, with appropriate substitutions, on the machine you're going to be logging in from:

    ssh-keygen -t ed25519 -C "me@my-domain.tld" # if you need a new key, ed25519 is the latest and possibly most secure option
    ssh-keygen -t rsa -b 4096 -C "me@my-domain.tld" # alternatively, use RSA and go (4,096 bits) large
    ssh root@myvpn.example.net # if your host forces a password change before anything else (e.g. Hetzner), do it now, then exit
    ssh-copy-id -i ~/.ssh/id_ed25519 root@myvpn.example.net # copy your public key over to the VPN server
    ssh root@myvpn.example.net # log back in to the server for the next step ...
    
  3. On your new server installation, become root, download the script, give it execute permissions, and run it:

    wget https://raw.githubusercontent.com/jawj/IKEv2-setup/master/setup.sh
    chmod u+x setup.sh
    ./setup.sh
    
  4. You'll be prompted to enter all the necessary details after the software updates and installations complete. If you are not using key-based SSH authentication, you must pick a really strong password for the login user when prompted, or your server will be compromised.

    The part of your session where the script asks you questions should look something like this:

     --- Configuration: VPN settings ---
    Network interface: eth0
    External IP: 100.100.100.100
    ** Note: hostname must resolve to this machine already, to enable Let's Encrypt certificate setup **
    Hostname for VPN: VPN username: george
    VPN password (no quotes, please): Confirm VPN password: Public DNS servers include:
    176.103.130.130,176.103.130.131 AdGuard https://adguard.com/en/adguard-dns/overview.html
    176.103.130.132,176.103.130.134 AdGuard Family https://adguard.com/en/adguard-dns/overview.html
    1.1.1.1,1.0.0.1 Cloudflare/APNIC https://1.1.1.1
    84.200.69.80,84.200.70.40 DNS.WATCH https://dns.watch
    8.8.8.8,8.8.4.4 Google https://developers.google.com/speed/public-dns/
    208.67.222.222,208.67.220.220 OpenDNS https://www.opendns.com
    208.67.222.123,208.67.220.123 OpenDNS FamilyShield https://www.opendns.com
    9.9.9.9,149.112.112.112 Quad9 https://quad9.net
    77.88.8.8,77.88.8.1 Yandex https://dns.yandex.com
    77.88.8.88,77.88.8.2 Yandex Safe https://dns.yandex.com
    77.88.8.7,77.88.8.3 Yandex Family https://dns.yandex.com
    DNS servers for VPN users (default: 1.1.1.1,1.0.0.1): 176.103.130.130,176.103.130.131
    --- Configuration: general server settings ---
    Timezone (default: Europe/London): Email address for sysadmin (e.g. j.bloggs@example.com): me@my-domain.tld
    Desired SSH log-in port (default: 22): 2222
    New SSH log-in user name: george
    Copy /root/.ssh/authorized_keys to new user and disable SSH password log-in [Y/n]? y
    New SSH user's password (e.g. for sudo): Confirm new SSH user's password: 
  5. Once you're up and running, use these commands for some insight into what's going on:

     sudo ipsec statusall # status, who's connected, etc.
    sudo iptables -L -v # how much traffic has been forwarded, dropped, etc.?
    sudo tail -f /var/log/syslog # real-time logs of (dis)connections etc.
    

Troubleshooting

If things don't work out right away ...

  • On the client: make sure you created the connection using the newly emailed .mobileconfig file or PowerShell commands. Setting it up manually via the OS GUI will not work, since it will default to insecure ciphers which the server has not been configured to support. Also note that .mobileconfig files generated with earlier iterations of this script may no longer be compatible, since the configured ciphers have changed from time to time.

  • On the server: check that network ingress for UDP on ports 500 and 4500 is enabled (on some cloud platforms you'll have to add appropriate firewall rules to your virtual network). Also check that packet forwarding is enabled (on some cloud platforms this is controlled by a configuration setting that's off by default).

  • Check the server logs on strongSwan startup and when you try to connect, and the client logs when you try to connect.

    • On the server: Log in via SSH, then sudo tail -f /var/log/syslog. To see startup logs, log in to another session and sudo ipsec restart there, then switch back. To see what's logged during a connection attempt, try to connect from a client.

    • On the client: On a Mac, open Console.app in /Applications/Utilities. If connecting from an iPhone, plug the iPhone into the Mac. Pick the relevant device (in the bar down the left), filter the output (in the box at top right) to nesession, and try to connect. (On Windows or Linux I don't know where you find the logs — if you know, feel free to write the explanation and send a pull request).

  • The setup script is now more or less idempotent — you should be able to run it repeatedly with no ill effects — so, when you've fixed any issues, simply run it again.

  • If you have a tricky question about strongSwan, it's probably better to raise it with the strongSwan team than file an issue here.

Users

To add or change VPN users, it's:

 sudo nano /etc/ipsec.secrets

Edit usernames and passwords as you see fit (but don't touch the first line, which specifies the server certificate). The line format for each user is:

 someusername : EAP "somepassword"

To exit nano it's Ctrl + O then Ctrl + X, and to have strongSwan pick up the changes it's:

 sudo ipsec secrets

Upgrades

If you're on a pre-18.04 version of Ubuntu, it's probably easiest to make a record of any changes to ipsec.secrets, blow the whole thing away and reinstall, then reinstate ipsec.secrets.

Note that you may also need to delete and recreate all your client connection settings using the updated PowerShell commands or .mobileconfig file, since there have been a few cipher changes over time.

Bonus paranoia

Your traffic is not logged on the server, but if you're feeling especially paranoid there are various things you could do to reduce logging further. A simple and somewhat drastic option (once you've got everything working) is:

 sudo rm /var/log/syslog && sudo ln -s /dev/null /var/log/syslog
sudo rm /var/log/auth.log && sudo ln -s /dev/null /var/log/auth.log

Why?

We use a similar setup as a corporate VPN at PSYT. And I use this to bounce my personal web browsing via Europe, in the hope of giving Theresa May's Investigatory Powers Bill the finger.

Why IKEv2?

  • Fair security
  • Built-in clients for latest iOS, Mac and Windows (+ trustworthy free install on Android)
  • Connect on demand support on iOS and Mac
  • Robust to connection switching and interruptions via MOBIKE

More on IKEv2 at https://www.cl.cam.ac.uk/~mas90/resources/strongswan/ and https://www.bestvpn.com/blog/4147/pptp-vs-l2tp-vs-openvpn-vs-sstp-vs-ikev2/

Why not Algo?

Feel free to use Algo instead. It has similar aims, and now configures WireGuard too. However, it has many more moving parts, and requires several local installation steps before you even start setting up your VPN. This script is intended to be much simpler.

About

Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - devops35/IKEv2-setup: Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server · GitHub
Skip to content

Latest commit

History

140 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

IKEv2-setup

Table of contents

What?

A Bash script that takes Ubuntu Server 20.04 LTS or 18.04 LTS from clean install to production-ready IKEv2 VPN with strongSwan. Comments and pull requests welcome. It may still work on 17.10, 17.04 or 16.10 if you remove the version check, but these are not tested.

VPN server

  • The VPN server identifies itself with a Let's Encrypt certificate, so there's no need for clients to install private certificates — they can simply authenticate with username and strong password (EAP-MSCHAPv2).

  • The only cipher set implemented is CNSA/RFC 6379 Suite B with confidentiality/encryption.

  • The box is firewalled with iptables and configured for unattended security upgrades, and the Let's Encrypt certificate is set up to auto-renew, so it could be safe to forget about it all until 18.04 reaches end-of-life in 2023. (Note that iptables setup includes basic rate-limiting, dropping new connections if there have been 60+ connection attempts in the last 5 minutes).

VPN clients

The VPN is tested working with:

  • macOS 10.12 – 10.15, iOS 10 – 13 — Built-in clients. A .mobileconfig profile is generated for Mac and iOS, to set up secure ciphers and enable Connect on demand support.
  • Windows 10 Pro — Built-in client. PowerShell commands are generated to configure the VPN and secure ciphers.
  • Ubuntu (17.04 and presumably others) — Using strongSwan. A Bash script is generated to set this up.
  • Android — Using the official strongSwan app.

Configuration files, scripts and instructions are sent by email. They are also dropped in the newly-created non-root user's home directory on the server (this point may be important, because VPS providers sometimes block traffic on port 25 by default and, even if successfully sent, conscientious email hosts will sometimes mark the email as spam).

Caveats

  • There's no IPv6 support — and, in fact, IPv6 networking is disabled — because supporting IPv6 prevents the use of forceencaps, and honestly also because I haven't got to grips with the security implications (ip6tables rules and so on).
  • The script won't work as-is on 16.04 LTS because the certbot package is outdated, found under the name letsencrypt, and doesn't renew certificates automatically.
  • Don't use this unmodified on a server you use for anything else: it does as it sees fit with various wider settings that may conflict with what you're doing.

How?

  1. Pick a domain name for the VPN server and ensure that it already resolves to the correct IP by creating the appropriate A record in the DNS and making sure it has propagated. Let's Encrypt needs this in order to create your server certificate.

Don't want to use your own domain name here? You could try using the reverse DNS name provided by your server host, or an automatic IP/DNS alias service such as sslip.io, xip.io, nip.io, s.test.cab, or xip.lhjmmc.cn (earlier versions of this script used an sslip.io address by default). However, both of these options may fall foul of Let's Encrypt's per-domain rate limit of 50 certificates per week. Note that ephemeral AWS domain names like ec2-34-267-212-76.compute-1.amazonaws.comare not accepted by Let's Encrypt.

  1. Start with a clean Ubuntu 20.04 or 18.04 Server installation. The cheapest VPSs offered by Linode, OVH, vps.ag, Google, Hetzner and Vultr, and Scaleway's ARM64-2GB, have all been tested working. On Scaleway, unblock SMTP ports in the admin panel and hard reboot the server first, or your configuration email will not be delivered. On Vultr, port 25 may also be blocked, but you won't know, and the only way to fix it is to open a support ticket.

  2. Optionally, set up key-based SSH authentication (alternatively, this may have been handled automatically by your server provider, or you may choose to stick with password-based authentication). This may require you to run some or all of the following commands, with appropriate substitutions, on the machine you're going to be logging in from:

    ssh-keygen -t ed25519 -C "me@my-domain.tld" # if you need a new key, ed25519 is the latest and possibly most secure option
    ssh-keygen -t rsa -b 4096 -C "me@my-domain.tld" # alternatively, use RSA and go (4,096 bits) large
    ssh root@myvpn.example.net # if your host forces a password change before anything else (e.g. Hetzner), do it now, then exit
    ssh-copy-id -i ~/.ssh/id_ed25519 root@myvpn.example.net # copy your public key over to the VPN server
    ssh root@myvpn.example.net # log back in to the server for the next step ...
    
  3. On your new server installation, become root, download the script, give it execute permissions, and run it:

    wget https://raw.githubusercontent.com/jawj/IKEv2-setup/master/setup.sh
    chmod u+x setup.sh
    ./setup.sh
    
  4. You'll be prompted to enter all the necessary details after the software updates and installations complete. If you are not using key-based SSH authentication, you must pick a really strong password for the login user when prompted, or your server will be compromised.

    The part of your session where the script asks you questions should look something like this:

     --- Configuration: VPN settings ---
    Network interface: eth0
    External IP: 100.100.100.100
    ** Note: hostname must resolve to this machine already, to enable Let's Encrypt certificate setup **
    Hostname for VPN: VPN username: george
    VPN password (no quotes, please): Confirm VPN password: Public DNS servers include:
    176.103.130.130,176.103.130.131 AdGuard https://adguard.com/en/adguard-dns/overview.html
    176.103.130.132,176.103.130.134 AdGuard Family https://adguard.com/en/adguard-dns/overview.html
    1.1.1.1,1.0.0.1 Cloudflare/APNIC https://1.1.1.1
    84.200.69.80,84.200.70.40 DNS.WATCH https://dns.watch
    8.8.8.8,8.8.4.4 Google https://developers.google.com/speed/public-dns/
    208.67.222.222,208.67.220.220 OpenDNS https://www.opendns.com
    208.67.222.123,208.67.220.123 OpenDNS FamilyShield https://www.opendns.com
    9.9.9.9,149.112.112.112 Quad9 https://quad9.net
    77.88.8.8,77.88.8.1 Yandex https://dns.yandex.com
    77.88.8.88,77.88.8.2 Yandex Safe https://dns.yandex.com
    77.88.8.7,77.88.8.3 Yandex Family https://dns.yandex.com
    DNS servers for VPN users (default: 1.1.1.1,1.0.0.1): 176.103.130.130,176.103.130.131
    --- Configuration: general server settings ---
    Timezone (default: Europe/London): Email address for sysadmin (e.g. j.bloggs@example.com): me@my-domain.tld
    Desired SSH log-in port (default: 22): 2222
    New SSH log-in user name: george
    Copy /root/.ssh/authorized_keys to new user and disable SSH password log-in [Y/n]? y
    New SSH user's password (e.g. for sudo): Confirm new SSH user's password: 
  5. Once you're up and running, use these commands for some insight into what's going on:

     sudo ipsec statusall # status, who's connected, etc.
    sudo iptables -L -v # how much traffic has been forwarded, dropped, etc.?
    sudo tail -f /var/log/syslog # real-time logs of (dis)connections etc.
    

Troubleshooting

If things don't work out right away ...

  • On the client: make sure you created the connection using the newly emailed .mobileconfig file or PowerShell commands. Setting it up manually via the OS GUI will not work, since it will default to insecure ciphers which the server has not been configured to support. Also note that .mobileconfig files generated with earlier iterations of this script may no longer be compatible, since the configured ciphers have changed from time to time.

  • On the server: check that network ingress for UDP on ports 500 and 4500 is enabled (on some cloud platforms you'll have to add appropriate firewall rules to your virtual network). Also check that packet forwarding is enabled (on some cloud platforms this is controlled by a configuration setting that's off by default).

  • Check the server logs on strongSwan startup and when you try to connect, and the client logs when you try to connect.

    • On the server: Log in via SSH, then sudo tail -f /var/log/syslog. To see startup logs, log in to another session and sudo ipsec restart there, then switch back. To see what's logged during a connection attempt, try to connect from a client.

    • On the client: On a Mac, open Console.app in /Applications/Utilities. If connecting from an iPhone, plug the iPhone into the Mac. Pick the relevant device (in the bar down the left), filter the output (in the box at top right) to nesession, and try to connect. (On Windows or Linux I don't know where you find the logs — if you know, feel free to write the explanation and send a pull request).

  • The setup script is now more or less idempotent — you should be able to run it repeatedly with no ill effects — so, when you've fixed any issues, simply run it again.

  • If you have a tricky question about strongSwan, it's probably better to raise it with the strongSwan team than file an issue here.

Users

To add or change VPN users, it's:

 sudo nano /etc/ipsec.secrets

Edit usernames and passwords as you see fit (but don't touch the first line, which specifies the server certificate). The line format for each user is:

 someusername : EAP "somepassword"

To exit nano it's Ctrl + O then Ctrl + X, and to have strongSwan pick up the changes it's:

 sudo ipsec secrets

Upgrades

If you're on a pre-18.04 version of Ubuntu, it's probably easiest to make a record of any changes to ipsec.secrets, blow the whole thing away and reinstall, then reinstate ipsec.secrets.

Note that you may also need to delete and recreate all your client connection settings using the updated PowerShell commands or .mobileconfig file, since there have been a few cipher changes over time.

Bonus paranoia

Your traffic is not logged on the server, but if you're feeling especially paranoid there are various things you could do to reduce logging further. A simple and somewhat drastic option (once you've got everything working) is:

 sudo rm /var/log/syslog && sudo ln -s /dev/null /var/log/syslog
sudo rm /var/log/auth.log && sudo ln -s /dev/null /var/log/auth.log

Why?

We use a similar setup as a corporate VPN at PSYT. And I use this to bounce my personal web browsing via Europe, in the hope of giving Theresa May's Investigatory Powers Bill the finger.

Why IKEv2?

  • Fair security
  • Built-in clients for latest iOS, Mac and Windows (+ trustworthy free install on Android)
  • Connect on demand support on iOS and Mac
  • Robust to connection switching and interruptions via MOBIKE

More on IKEv2 at https://www.cl.cam.ac.uk/~mas90/resources/strongswan/ and https://www.bestvpn.com/blog/4147/pptp-vs-l2tp-vs-openvpn-vs-sstp-vs-ikev2/

Why not Algo?

Feel free to use Algo instead. It has similar aims, and now configures WireGuard too. However, it has many more moving parts, and requires several local installation steps before you even start setting up your VPN. This script is intended to be much simpler.

About

Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - devops35/IKEv2-setup: Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server · GitHub
Skip to content

Latest commit

History

140 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

IKEv2-setup

Table of contents

What?

A Bash script that takes Ubuntu Server 20.04 LTS or 18.04 LTS from clean install to production-ready IKEv2 VPN with strongSwan. Comments and pull requests welcome. It may still work on 17.10, 17.04 or 16.10 if you remove the version check, but these are not tested.

VPN server

  • The VPN server identifies itself with a Let's Encrypt certificate, so there's no need for clients to install private certificates — they can simply authenticate with username and strong password (EAP-MSCHAPv2).

  • The only cipher set implemented is CNSA/RFC 6379 Suite B with confidentiality/encryption.

  • The box is firewalled with iptables and configured for unattended security upgrades, and the Let's Encrypt certificate is set up to auto-renew, so it could be safe to forget about it all until 18.04 reaches end-of-life in 2023. (Note that iptables setup includes basic rate-limiting, dropping new connections if there have been 60+ connection attempts in the last 5 minutes).

VPN clients

The VPN is tested working with:

  • macOS 10.12 – 10.15, iOS 10 – 13 — Built-in clients. A .mobileconfig profile is generated for Mac and iOS, to set up secure ciphers and enable Connect on demand support.
  • Windows 10 Pro — Built-in client. PowerShell commands are generated to configure the VPN and secure ciphers.
  • Ubuntu (17.04 and presumably others) — Using strongSwan. A Bash script is generated to set this up.
  • Android — Using the official strongSwan app.

Configuration files, scripts and instructions are sent by email. They are also dropped in the newly-created non-root user's home directory on the server (this point may be important, because VPS providers sometimes block traffic on port 25 by default and, even if successfully sent, conscientious email hosts will sometimes mark the email as spam).

Caveats

  • There's no IPv6 support — and, in fact, IPv6 networking is disabled — because supporting IPv6 prevents the use of forceencaps, and honestly also because I haven't got to grips with the security implications (ip6tables rules and so on).
  • The script won't work as-is on 16.04 LTS because the certbot package is outdated, found under the name letsencrypt, and doesn't renew certificates automatically.
  • Don't use this unmodified on a server you use for anything else: it does as it sees fit with various wider settings that may conflict with what you're doing.

How?

  1. Pick a domain name for the VPN server and ensure that it already resolves to the correct IP by creating the appropriate A record in the DNS and making sure it has propagated. Let's Encrypt needs this in order to create your server certificate.

Don't want to use your own domain name here? You could try using the reverse DNS name provided by your server host, or an automatic IP/DNS alias service such as sslip.io, xip.io, nip.io, s.test.cab, or xip.lhjmmc.cn (earlier versions of this script used an sslip.io address by default). However, both of these options may fall foul of Let's Encrypt's per-domain rate limit of 50 certificates per week. Note that ephemeral AWS domain names like ec2-34-267-212-76.compute-1.amazonaws.comare not accepted by Let's Encrypt.

  1. Start with a clean Ubuntu 20.04 or 18.04 Server installation. The cheapest VPSs offered by Linode, OVH, vps.ag, Google, Hetzner and Vultr, and Scaleway's ARM64-2GB, have all been tested working. On Scaleway, unblock SMTP ports in the admin panel and hard reboot the server first, or your configuration email will not be delivered. On Vultr, port 25 may also be blocked, but you won't know, and the only way to fix it is to open a support ticket.

  2. Optionally, set up key-based SSH authentication (alternatively, this may have been handled automatically by your server provider, or you may choose to stick with password-based authentication). This may require you to run some or all of the following commands, with appropriate substitutions, on the machine you're going to be logging in from:

    ssh-keygen -t ed25519 -C "me@my-domain.tld" # if you need a new key, ed25519 is the latest and possibly most secure option
    ssh-keygen -t rsa -b 4096 -C "me@my-domain.tld" # alternatively, use RSA and go (4,096 bits) large
    ssh root@myvpn.example.net # if your host forces a password change before anything else (e.g. Hetzner), do it now, then exit
    ssh-copy-id -i ~/.ssh/id_ed25519 root@myvpn.example.net # copy your public key over to the VPN server
    ssh root@myvpn.example.net # log back in to the server for the next step ...
    
  3. On your new server installation, become root, download the script, give it execute permissions, and run it:

    wget https://raw.githubusercontent.com/jawj/IKEv2-setup/master/setup.sh
    chmod u+x setup.sh
    ./setup.sh
    
  4. You'll be prompted to enter all the necessary details after the software updates and installations complete. If you are not using key-based SSH authentication, you must pick a really strong password for the login user when prompted, or your server will be compromised.

    The part of your session where the script asks you questions should look something like this:

     --- Configuration: VPN settings ---
    Network interface: eth0
    External IP: 100.100.100.100
    ** Note: hostname must resolve to this machine already, to enable Let's Encrypt certificate setup **
    Hostname for VPN: VPN username: george
    VPN password (no quotes, please): Confirm VPN password: Public DNS servers include:
    176.103.130.130,176.103.130.131 AdGuard https://adguard.com/en/adguard-dns/overview.html
    176.103.130.132,176.103.130.134 AdGuard Family https://adguard.com/en/adguard-dns/overview.html
    1.1.1.1,1.0.0.1 Cloudflare/APNIC https://1.1.1.1
    84.200.69.80,84.200.70.40 DNS.WATCH https://dns.watch
    8.8.8.8,8.8.4.4 Google https://developers.google.com/speed/public-dns/
    208.67.222.222,208.67.220.220 OpenDNS https://www.opendns.com
    208.67.222.123,208.67.220.123 OpenDNS FamilyShield https://www.opendns.com
    9.9.9.9,149.112.112.112 Quad9 https://quad9.net
    77.88.8.8,77.88.8.1 Yandex https://dns.yandex.com
    77.88.8.88,77.88.8.2 Yandex Safe https://dns.yandex.com
    77.88.8.7,77.88.8.3 Yandex Family https://dns.yandex.com
    DNS servers for VPN users (default: 1.1.1.1,1.0.0.1): 176.103.130.130,176.103.130.131
    --- Configuration: general server settings ---
    Timezone (default: Europe/London): Email address for sysadmin (e.g. j.bloggs@example.com): me@my-domain.tld
    Desired SSH log-in port (default: 22): 2222
    New SSH log-in user name: george
    Copy /root/.ssh/authorized_keys to new user and disable SSH password log-in [Y/n]? y
    New SSH user's password (e.g. for sudo): Confirm new SSH user's password: 
  5. Once you're up and running, use these commands for some insight into what's going on:

     sudo ipsec statusall # status, who's connected, etc.
    sudo iptables -L -v # how much traffic has been forwarded, dropped, etc.?
    sudo tail -f /var/log/syslog # real-time logs of (dis)connections etc.
    

Troubleshooting

If things don't work out right away ...

  • On the client: make sure you created the connection using the newly emailed .mobileconfig file or PowerShell commands. Setting it up manually via the OS GUI will not work, since it will default to insecure ciphers which the server has not been configured to support. Also note that .mobileconfig files generated with earlier iterations of this script may no longer be compatible, since the configured ciphers have changed from time to time.

  • On the server: check that network ingress for UDP on ports 500 and 4500 is enabled (on some cloud platforms you'll have to add appropriate firewall rules to your virtual network). Also check that packet forwarding is enabled (on some cloud platforms this is controlled by a configuration setting that's off by default).

  • Check the server logs on strongSwan startup and when you try to connect, and the client logs when you try to connect.

    • On the server: Log in via SSH, then sudo tail -f /var/log/syslog. To see startup logs, log in to another session and sudo ipsec restart there, then switch back. To see what's logged during a connection attempt, try to connect from a client.

    • On the client: On a Mac, open Console.app in /Applications/Utilities. If connecting from an iPhone, plug the iPhone into the Mac. Pick the relevant device (in the bar down the left), filter the output (in the box at top right) to nesession, and try to connect. (On Windows or Linux I don't know where you find the logs — if you know, feel free to write the explanation and send a pull request).

  • The setup script is now more or less idempotent — you should be able to run it repeatedly with no ill effects — so, when you've fixed any issues, simply run it again.

  • If you have a tricky question about strongSwan, it's probably better to raise it with the strongSwan team than file an issue here.

Users

To add or change VPN users, it's:

 sudo nano /etc/ipsec.secrets

Edit usernames and passwords as you see fit (but don't touch the first line, which specifies the server certificate). The line format for each user is:

 someusername : EAP "somepassword"

To exit nano it's Ctrl + O then Ctrl + X, and to have strongSwan pick up the changes it's:

 sudo ipsec secrets

Upgrades

If you're on a pre-18.04 version of Ubuntu, it's probably easiest to make a record of any changes to ipsec.secrets, blow the whole thing away and reinstall, then reinstate ipsec.secrets.

Note that you may also need to delete and recreate all your client connection settings using the updated PowerShell commands or .mobileconfig file, since there have been a few cipher changes over time.

Bonus paranoia

Your traffic is not logged on the server, but if you're feeling especially paranoid there are various things you could do to reduce logging further. A simple and somewhat drastic option (once you've got everything working) is:

 sudo rm /var/log/syslog && sudo ln -s /dev/null /var/log/syslog
sudo rm /var/log/auth.log && sudo ln -s /dev/null /var/log/auth.log

Why?

We use a similar setup as a corporate VPN at PSYT. And I use this to bounce my personal web browsing via Europe, in the hope of giving Theresa May's Investigatory Powers Bill the finger.

Why IKEv2?

  • Fair security
  • Built-in clients for latest iOS, Mac and Windows (+ trustworthy free install on Android)
  • Connect on demand support on iOS and Mac
  • Robust to connection switching and interruptions via MOBIKE

More on IKEv2 at https://www.cl.cam.ac.uk/~mas90/resources/strongswan/ and https://www.bestvpn.com/blog/4147/pptp-vs-l2tp-vs-openvpn-vs-sstp-vs-ikev2/

Why not Algo?

Feel free to use Algo instead. It has similar aims, and now configures WireGuard too. However, it has many more moving parts, and requires several local installation steps before you even start setting up your VPN. This script is intended to be much simpler.

About

Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - devops35/IKEv2-setup: Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server · GitHub
Skip to content

Latest commit

History

140 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

IKEv2-setup

Table of contents

What?

A Bash script that takes Ubuntu Server 20.04 LTS or 18.04 LTS from clean install to production-ready IKEv2 VPN with strongSwan. Comments and pull requests welcome. It may still work on 17.10, 17.04 or 16.10 if you remove the version check, but these are not tested.

VPN server

  • The VPN server identifies itself with a Let's Encrypt certificate, so there's no need for clients to install private certificates — they can simply authenticate with username and strong password (EAP-MSCHAPv2).

  • The only cipher set implemented is CNSA/RFC 6379 Suite B with confidentiality/encryption.

  • The box is firewalled with iptables and configured for unattended security upgrades, and the Let's Encrypt certificate is set up to auto-renew, so it could be safe to forget about it all until 18.04 reaches end-of-life in 2023. (Note that iptables setup includes basic rate-limiting, dropping new connections if there have been 60+ connection attempts in the last 5 minutes).

VPN clients

The VPN is tested working with:

  • macOS 10.12 – 10.15, iOS 10 – 13 — Built-in clients. A .mobileconfig profile is generated for Mac and iOS, to set up secure ciphers and enable Connect on demand support.
  • Windows 10 Pro — Built-in client. PowerShell commands are generated to configure the VPN and secure ciphers.
  • Ubuntu (17.04 and presumably others) — Using strongSwan. A Bash script is generated to set this up.
  • Android — Using the official strongSwan app.

Configuration files, scripts and instructions are sent by email. They are also dropped in the newly-created non-root user's home directory on the server (this point may be important, because VPS providers sometimes block traffic on port 25 by default and, even if successfully sent, conscientious email hosts will sometimes mark the email as spam).

Caveats

  • There's no IPv6 support — and, in fact, IPv6 networking is disabled — because supporting IPv6 prevents the use of forceencaps, and honestly also because I haven't got to grips with the security implications (ip6tables rules and so on).
  • The script won't work as-is on 16.04 LTS because the certbot package is outdated, found under the name letsencrypt, and doesn't renew certificates automatically.
  • Don't use this unmodified on a server you use for anything else: it does as it sees fit with various wider settings that may conflict with what you're doing.

How?

  1. Pick a domain name for the VPN server and ensure that it already resolves to the correct IP by creating the appropriate A record in the DNS and making sure it has propagated. Let's Encrypt needs this in order to create your server certificate.

Don't want to use your own domain name here? You could try using the reverse DNS name provided by your server host, or an automatic IP/DNS alias service such as sslip.io, xip.io, nip.io, s.test.cab, or xip.lhjmmc.cn (earlier versions of this script used an sslip.io address by default). However, both of these options may fall foul of Let's Encrypt's per-domain rate limit of 50 certificates per week. Note that ephemeral AWS domain names like ec2-34-267-212-76.compute-1.amazonaws.comare not accepted by Let's Encrypt.

  1. Start with a clean Ubuntu 20.04 or 18.04 Server installation. The cheapest VPSs offered by Linode, OVH, vps.ag, Google, Hetzner and Vultr, and Scaleway's ARM64-2GB, have all been tested working. On Scaleway, unblock SMTP ports in the admin panel and hard reboot the server first, or your configuration email will not be delivered. On Vultr, port 25 may also be blocked, but you won't know, and the only way to fix it is to open a support ticket.

  2. Optionally, set up key-based SSH authentication (alternatively, this may have been handled automatically by your server provider, or you may choose to stick with password-based authentication). This may require you to run some or all of the following commands, with appropriate substitutions, on the machine you're going to be logging in from:

    ssh-keygen -t ed25519 -C "me@my-domain.tld" # if you need a new key, ed25519 is the latest and possibly most secure option
    ssh-keygen -t rsa -b 4096 -C "me@my-domain.tld" # alternatively, use RSA and go (4,096 bits) large
    ssh root@myvpn.example.net # if your host forces a password change before anything else (e.g. Hetzner), do it now, then exit
    ssh-copy-id -i ~/.ssh/id_ed25519 root@myvpn.example.net # copy your public key over to the VPN server
    ssh root@myvpn.example.net # log back in to the server for the next step ...
    
  3. On your new server installation, become root, download the script, give it execute permissions, and run it:

    wget https://raw.githubusercontent.com/jawj/IKEv2-setup/master/setup.sh
    chmod u+x setup.sh
    ./setup.sh
    
  4. You'll be prompted to enter all the necessary details after the software updates and installations complete. If you are not using key-based SSH authentication, you must pick a really strong password for the login user when prompted, or your server will be compromised.

    The part of your session where the script asks you questions should look something like this:

     --- Configuration: VPN settings ---
    Network interface: eth0
    External IP: 100.100.100.100
    ** Note: hostname must resolve to this machine already, to enable Let's Encrypt certificate setup **
    Hostname for VPN: VPN username: george
    VPN password (no quotes, please): Confirm VPN password: Public DNS servers include:
    176.103.130.130,176.103.130.131 AdGuard https://adguard.com/en/adguard-dns/overview.html
    176.103.130.132,176.103.130.134 AdGuard Family https://adguard.com/en/adguard-dns/overview.html
    1.1.1.1,1.0.0.1 Cloudflare/APNIC https://1.1.1.1
    84.200.69.80,84.200.70.40 DNS.WATCH https://dns.watch
    8.8.8.8,8.8.4.4 Google https://developers.google.com/speed/public-dns/
    208.67.222.222,208.67.220.220 OpenDNS https://www.opendns.com
    208.67.222.123,208.67.220.123 OpenDNS FamilyShield https://www.opendns.com
    9.9.9.9,149.112.112.112 Quad9 https://quad9.net
    77.88.8.8,77.88.8.1 Yandex https://dns.yandex.com
    77.88.8.88,77.88.8.2 Yandex Safe https://dns.yandex.com
    77.88.8.7,77.88.8.3 Yandex Family https://dns.yandex.com
    DNS servers for VPN users (default: 1.1.1.1,1.0.0.1): 176.103.130.130,176.103.130.131
    --- Configuration: general server settings ---
    Timezone (default: Europe/London): Email address for sysadmin (e.g. j.bloggs@example.com): me@my-domain.tld
    Desired SSH log-in port (default: 22): 2222
    New SSH log-in user name: george
    Copy /root/.ssh/authorized_keys to new user and disable SSH password log-in [Y/n]? y
    New SSH user's password (e.g. for sudo): Confirm new SSH user's password: 
  5. Once you're up and running, use these commands for some insight into what's going on:

     sudo ipsec statusall # status, who's connected, etc.
    sudo iptables -L -v # how much traffic has been forwarded, dropped, etc.?
    sudo tail -f /var/log/syslog # real-time logs of (dis)connections etc.
    

Troubleshooting

If things don't work out right away ...

  • On the client: make sure you created the connection using the newly emailed .mobileconfig file or PowerShell commands. Setting it up manually via the OS GUI will not work, since it will default to insecure ciphers which the server has not been configured to support. Also note that .mobileconfig files generated with earlier iterations of this script may no longer be compatible, since the configured ciphers have changed from time to time.

  • On the server: check that network ingress for UDP on ports 500 and 4500 is enabled (on some cloud platforms you'll have to add appropriate firewall rules to your virtual network). Also check that packet forwarding is enabled (on some cloud platforms this is controlled by a configuration setting that's off by default).

  • Check the server logs on strongSwan startup and when you try to connect, and the client logs when you try to connect.

    • On the server: Log in via SSH, then sudo tail -f /var/log/syslog. To see startup logs, log in to another session and sudo ipsec restart there, then switch back. To see what's logged during a connection attempt, try to connect from a client.

    • On the client: On a Mac, open Console.app in /Applications/Utilities. If connecting from an iPhone, plug the iPhone into the Mac. Pick the relevant device (in the bar down the left), filter the output (in the box at top right) to nesession, and try to connect. (On Windows or Linux I don't know where you find the logs — if you know, feel free to write the explanation and send a pull request).

  • The setup script is now more or less idempotent — you should be able to run it repeatedly with no ill effects — so, when you've fixed any issues, simply run it again.

  • If you have a tricky question about strongSwan, it's probably better to raise it with the strongSwan team than file an issue here.

Users

To add or change VPN users, it's:

 sudo nano /etc/ipsec.secrets

Edit usernames and passwords as you see fit (but don't touch the first line, which specifies the server certificate). The line format for each user is:

 someusername : EAP "somepassword"

To exit nano it's Ctrl + O then Ctrl + X, and to have strongSwan pick up the changes it's:

 sudo ipsec secrets

Upgrades

If you're on a pre-18.04 version of Ubuntu, it's probably easiest to make a record of any changes to ipsec.secrets, blow the whole thing away and reinstall, then reinstate ipsec.secrets.

Note that you may also need to delete and recreate all your client connection settings using the updated PowerShell commands or .mobileconfig file, since there have been a few cipher changes over time.

Bonus paranoia

Your traffic is not logged on the server, but if you're feeling especially paranoid there are various things you could do to reduce logging further. A simple and somewhat drastic option (once you've got everything working) is:

 sudo rm /var/log/syslog && sudo ln -s /dev/null /var/log/syslog
sudo rm /var/log/auth.log && sudo ln -s /dev/null /var/log/auth.log

Why?

We use a similar setup as a corporate VPN at PSYT. And I use this to bounce my personal web browsing via Europe, in the hope of giving Theresa May's Investigatory Powers Bill the finger.

Why IKEv2?

  • Fair security
  • Built-in clients for latest iOS, Mac and Windows (+ trustworthy free install on Android)
  • Connect on demand support on iOS and Mac
  • Robust to connection switching and interruptions via MOBIKE

More on IKEv2 at https://www.cl.cam.ac.uk/~mas90/resources/strongswan/ and https://www.bestvpn.com/blog/4147/pptp-vs-l2tp-vs-openvpn-vs-sstp-vs-ikev2/

Why not Algo?

Feel free to use Algo instead. It has similar aims, and now configures WireGuard too. However, it has many more moving parts, and requires several local installation steps before you even start setting up your VPN. This script is intended to be much simpler.

About

Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - devops35/IKEv2-setup: Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server · GitHub
Skip to content

Latest commit

History

140 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

IKEv2-setup

Table of contents

What?

A Bash script that takes Ubuntu Server 20.04 LTS or 18.04 LTS from clean install to production-ready IKEv2 VPN with strongSwan. Comments and pull requests welcome. It may still work on 17.10, 17.04 or 16.10 if you remove the version check, but these are not tested.

VPN server

  • The VPN server identifies itself with a Let's Encrypt certificate, so there's no need for clients to install private certificates — they can simply authenticate with username and strong password (EAP-MSCHAPv2).

  • The only cipher set implemented is CNSA/RFC 6379 Suite B with confidentiality/encryption.

  • The box is firewalled with iptables and configured for unattended security upgrades, and the Let's Encrypt certificate is set up to auto-renew, so it could be safe to forget about it all until 18.04 reaches end-of-life in 2023. (Note that iptables setup includes basic rate-limiting, dropping new connections if there have been 60+ connection attempts in the last 5 minutes).

VPN clients

The VPN is tested working with:

  • macOS 10.12 – 10.15, iOS 10 – 13 — Built-in clients. A .mobileconfig profile is generated for Mac and iOS, to set up secure ciphers and enable Connect on demand support.
  • Windows 10 Pro — Built-in client. PowerShell commands are generated to configure the VPN and secure ciphers.
  • Ubuntu (17.04 and presumably others) — Using strongSwan. A Bash script is generated to set this up.
  • Android — Using the official strongSwan app.

Configuration files, scripts and instructions are sent by email. They are also dropped in the newly-created non-root user's home directory on the server (this point may be important, because VPS providers sometimes block traffic on port 25 by default and, even if successfully sent, conscientious email hosts will sometimes mark the email as spam).

Caveats

  • There's no IPv6 support — and, in fact, IPv6 networking is disabled — because supporting IPv6 prevents the use of forceencaps, and honestly also because I haven't got to grips with the security implications (ip6tables rules and so on).
  • The script won't work as-is on 16.04 LTS because the certbot package is outdated, found under the name letsencrypt, and doesn't renew certificates automatically.
  • Don't use this unmodified on a server you use for anything else: it does as it sees fit with various wider settings that may conflict with what you're doing.

How?

  1. Pick a domain name for the VPN server and ensure that it already resolves to the correct IP by creating the appropriate A record in the DNS and making sure it has propagated. Let's Encrypt needs this in order to create your server certificate.

Don't want to use your own domain name here? You could try using the reverse DNS name provided by your server host, or an automatic IP/DNS alias service such as sslip.io, xip.io, nip.io, s.test.cab, or xip.lhjmmc.cn (earlier versions of this script used an sslip.io address by default). However, both of these options may fall foul of Let's Encrypt's per-domain rate limit of 50 certificates per week. Note that ephemeral AWS domain names like ec2-34-267-212-76.compute-1.amazonaws.comare not accepted by Let's Encrypt.

  1. Start with a clean Ubuntu 20.04 or 18.04 Server installation. The cheapest VPSs offered by Linode, OVH, vps.ag, Google, Hetzner and Vultr, and Scaleway's ARM64-2GB, have all been tested working. On Scaleway, unblock SMTP ports in the admin panel and hard reboot the server first, or your configuration email will not be delivered. On Vultr, port 25 may also be blocked, but you won't know, and the only way to fix it is to open a support ticket.

  2. Optionally, set up key-based SSH authentication (alternatively, this may have been handled automatically by your server provider, or you may choose to stick with password-based authentication). This may require you to run some or all of the following commands, with appropriate substitutions, on the machine you're going to be logging in from:

    ssh-keygen -t ed25519 -C "me@my-domain.tld" # if you need a new key, ed25519 is the latest and possibly most secure option
    ssh-keygen -t rsa -b 4096 -C "me@my-domain.tld" # alternatively, use RSA and go (4,096 bits) large
    ssh root@myvpn.example.net # if your host forces a password change before anything else (e.g. Hetzner), do it now, then exit
    ssh-copy-id -i ~/.ssh/id_ed25519 root@myvpn.example.net # copy your public key over to the VPN server
    ssh root@myvpn.example.net # log back in to the server for the next step ...
    
  3. On your new server installation, become root, download the script, give it execute permissions, and run it:

    wget https://raw.githubusercontent.com/jawj/IKEv2-setup/master/setup.sh
    chmod u+x setup.sh
    ./setup.sh
    
  4. You'll be prompted to enter all the necessary details after the software updates and installations complete. If you are not using key-based SSH authentication, you must pick a really strong password for the login user when prompted, or your server will be compromised.

    The part of your session where the script asks you questions should look something like this:

     --- Configuration: VPN settings ---
    Network interface: eth0
    External IP: 100.100.100.100
    ** Note: hostname must resolve to this machine already, to enable Let's Encrypt certificate setup **
    Hostname for VPN: VPN username: george
    VPN password (no quotes, please): Confirm VPN password: Public DNS servers include:
    176.103.130.130,176.103.130.131 AdGuard https://adguard.com/en/adguard-dns/overview.html
    176.103.130.132,176.103.130.134 AdGuard Family https://adguard.com/en/adguard-dns/overview.html
    1.1.1.1,1.0.0.1 Cloudflare/APNIC https://1.1.1.1
    84.200.69.80,84.200.70.40 DNS.WATCH https://dns.watch
    8.8.8.8,8.8.4.4 Google https://developers.google.com/speed/public-dns/
    208.67.222.222,208.67.220.220 OpenDNS https://www.opendns.com
    208.67.222.123,208.67.220.123 OpenDNS FamilyShield https://www.opendns.com
    9.9.9.9,149.112.112.112 Quad9 https://quad9.net
    77.88.8.8,77.88.8.1 Yandex https://dns.yandex.com
    77.88.8.88,77.88.8.2 Yandex Safe https://dns.yandex.com
    77.88.8.7,77.88.8.3 Yandex Family https://dns.yandex.com
    DNS servers for VPN users (default: 1.1.1.1,1.0.0.1): 176.103.130.130,176.103.130.131
    --- Configuration: general server settings ---
    Timezone (default: Europe/London): Email address for sysadmin (e.g. j.bloggs@example.com): me@my-domain.tld
    Desired SSH log-in port (default: 22): 2222
    New SSH log-in user name: george
    Copy /root/.ssh/authorized_keys to new user and disable SSH password log-in [Y/n]? y
    New SSH user's password (e.g. for sudo): Confirm new SSH user's password: 
  5. Once you're up and running, use these commands for some insight into what's going on:

     sudo ipsec statusall # status, who's connected, etc.
    sudo iptables -L -v # how much traffic has been forwarded, dropped, etc.?
    sudo tail -f /var/log/syslog # real-time logs of (dis)connections etc.
    

Troubleshooting

If things don't work out right away ...

  • On the client: make sure you created the connection using the newly emailed .mobileconfig file or PowerShell commands. Setting it up manually via the OS GUI will not work, since it will default to insecure ciphers which the server has not been configured to support. Also note that .mobileconfig files generated with earlier iterations of this script may no longer be compatible, since the configured ciphers have changed from time to time.

  • On the server: check that network ingress for UDP on ports 500 and 4500 is enabled (on some cloud platforms you'll have to add appropriate firewall rules to your virtual network). Also check that packet forwarding is enabled (on some cloud platforms this is controlled by a configuration setting that's off by default).

  • Check the server logs on strongSwan startup and when you try to connect, and the client logs when you try to connect.

    • On the server: Log in via SSH, then sudo tail -f /var/log/syslog. To see startup logs, log in to another session and sudo ipsec restart there, then switch back. To see what's logged during a connection attempt, try to connect from a client.

    • On the client: On a Mac, open Console.app in /Applications/Utilities. If connecting from an iPhone, plug the iPhone into the Mac. Pick the relevant device (in the bar down the left), filter the output (in the box at top right) to nesession, and try to connect. (On Windows or Linux I don't know where you find the logs — if you know, feel free to write the explanation and send a pull request).

  • The setup script is now more or less idempotent — you should be able to run it repeatedly with no ill effects — so, when you've fixed any issues, simply run it again.

  • If you have a tricky question about strongSwan, it's probably better to raise it with the strongSwan team than file an issue here.

Users

To add or change VPN users, it's:

 sudo nano /etc/ipsec.secrets

Edit usernames and passwords as you see fit (but don't touch the first line, which specifies the server certificate). The line format for each user is:

 someusername : EAP "somepassword"

To exit nano it's Ctrl + O then Ctrl + X, and to have strongSwan pick up the changes it's:

 sudo ipsec secrets

Upgrades

If you're on a pre-18.04 version of Ubuntu, it's probably easiest to make a record of any changes to ipsec.secrets, blow the whole thing away and reinstall, then reinstate ipsec.secrets.

Note that you may also need to delete and recreate all your client connection settings using the updated PowerShell commands or .mobileconfig file, since there have been a few cipher changes over time.

Bonus paranoia

Your traffic is not logged on the server, but if you're feeling especially paranoid there are various things you could do to reduce logging further. A simple and somewhat drastic option (once you've got everything working) is:

 sudo rm /var/log/syslog && sudo ln -s /dev/null /var/log/syslog
sudo rm /var/log/auth.log && sudo ln -s /dev/null /var/log/auth.log

Why?

We use a similar setup as a corporate VPN at PSYT. And I use this to bounce my personal web browsing via Europe, in the hope of giving Theresa May's Investigatory Powers Bill the finger.

Why IKEv2?

  • Fair security
  • Built-in clients for latest iOS, Mac and Windows (+ trustworthy free install on Android)
  • Connect on demand support on iOS and Mac
  • Robust to connection switching and interruptions via MOBIKE

More on IKEv2 at https://www.cl.cam.ac.uk/~mas90/resources/strongswan/ and https://www.bestvpn.com/blog/4147/pptp-vs-l2tp-vs-openvpn-vs-sstp-vs-ikev2/

Why not Algo?

Feel free to use Algo instead. It has similar aims, and now configures WireGuard too. However, it has many more moving parts, and requires several local installation steps before you even start setting up your VPN. This script is intended to be much simpler.

About

Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - devops35/IKEv2-setup: Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server · GitHub
Skip to content

Latest commit

History

140 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

IKEv2-setup

Table of contents

What?

A Bash script that takes Ubuntu Server 20.04 LTS or 18.04 LTS from clean install to production-ready IKEv2 VPN with strongSwan. Comments and pull requests welcome. It may still work on 17.10, 17.04 or 16.10 if you remove the version check, but these are not tested.

VPN server

  • The VPN server identifies itself with a Let's Encrypt certificate, so there's no need for clients to install private certificates — they can simply authenticate with username and strong password (EAP-MSCHAPv2).

  • The only cipher set implemented is CNSA/RFC 6379 Suite B with confidentiality/encryption.

  • The box is firewalled with iptables and configured for unattended security upgrades, and the Let's Encrypt certificate is set up to auto-renew, so it could be safe to forget about it all until 18.04 reaches end-of-life in 2023. (Note that iptables setup includes basic rate-limiting, dropping new connections if there have been 60+ connection attempts in the last 5 minutes).

VPN clients

The VPN is tested working with:

  • macOS 10.12 – 10.15, iOS 10 – 13 — Built-in clients. A .mobileconfig profile is generated for Mac and iOS, to set up secure ciphers and enable Connect on demand support.
  • Windows 10 Pro — Built-in client. PowerShell commands are generated to configure the VPN and secure ciphers.
  • Ubuntu (17.04 and presumably others) — Using strongSwan. A Bash script is generated to set this up.
  • Android — Using the official strongSwan app.

Configuration files, scripts and instructions are sent by email. They are also dropped in the newly-created non-root user's home directory on the server (this point may be important, because VPS providers sometimes block traffic on port 25 by default and, even if successfully sent, conscientious email hosts will sometimes mark the email as spam).

Caveats

  • There's no IPv6 support — and, in fact, IPv6 networking is disabled — because supporting IPv6 prevents the use of forceencaps, and honestly also because I haven't got to grips with the security implications (ip6tables rules and so on).
  • The script won't work as-is on 16.04 LTS because the certbot package is outdated, found under the name letsencrypt, and doesn't renew certificates automatically.
  • Don't use this unmodified on a server you use for anything else: it does as it sees fit with various wider settings that may conflict with what you're doing.

How?

  1. Pick a domain name for the VPN server and ensure that it already resolves to the correct IP by creating the appropriate A record in the DNS and making sure it has propagated. Let's Encrypt needs this in order to create your server certificate.

Don't want to use your own domain name here? You could try using the reverse DNS name provided by your server host, or an automatic IP/DNS alias service such as sslip.io, xip.io, nip.io, s.test.cab, or xip.lhjmmc.cn (earlier versions of this script used an sslip.io address by default). However, both of these options may fall foul of Let's Encrypt's per-domain rate limit of 50 certificates per week. Note that ephemeral AWS domain names like ec2-34-267-212-76.compute-1.amazonaws.comare not accepted by Let's Encrypt.

  1. Start with a clean Ubuntu 20.04 or 18.04 Server installation. The cheapest VPSs offered by Linode, OVH, vps.ag, Google, Hetzner and Vultr, and Scaleway's ARM64-2GB, have all been tested working. On Scaleway, unblock SMTP ports in the admin panel and hard reboot the server first, or your configuration email will not be delivered. On Vultr, port 25 may also be blocked, but you won't know, and the only way to fix it is to open a support ticket.

  2. Optionally, set up key-based SSH authentication (alternatively, this may have been handled automatically by your server provider, or you may choose to stick with password-based authentication). This may require you to run some or all of the following commands, with appropriate substitutions, on the machine you're going to be logging in from:

    ssh-keygen -t ed25519 -C "me@my-domain.tld" # if you need a new key, ed25519 is the latest and possibly most secure option
    ssh-keygen -t rsa -b 4096 -C "me@my-domain.tld" # alternatively, use RSA and go (4,096 bits) large
    ssh root@myvpn.example.net # if your host forces a password change before anything else (e.g. Hetzner), do it now, then exit
    ssh-copy-id -i ~/.ssh/id_ed25519 root@myvpn.example.net # copy your public key over to the VPN server
    ssh root@myvpn.example.net # log back in to the server for the next step ...
    
  3. On your new server installation, become root, download the script, give it execute permissions, and run it:

    wget https://raw.githubusercontent.com/jawj/IKEv2-setup/master/setup.sh
    chmod u+x setup.sh
    ./setup.sh
    
  4. You'll be prompted to enter all the necessary details after the software updates and installations complete. If you are not using key-based SSH authentication, you must pick a really strong password for the login user when prompted, or your server will be compromised.

    The part of your session where the script asks you questions should look something like this:

     --- Configuration: VPN settings ---
    Network interface: eth0
    External IP: 100.100.100.100
    ** Note: hostname must resolve to this machine already, to enable Let's Encrypt certificate setup **
    Hostname for VPN: VPN username: george
    VPN password (no quotes, please): Confirm VPN password: Public DNS servers include:
    176.103.130.130,176.103.130.131 AdGuard https://adguard.com/en/adguard-dns/overview.html
    176.103.130.132,176.103.130.134 AdGuard Family https://adguard.com/en/adguard-dns/overview.html
    1.1.1.1,1.0.0.1 Cloudflare/APNIC https://1.1.1.1
    84.200.69.80,84.200.70.40 DNS.WATCH https://dns.watch
    8.8.8.8,8.8.4.4 Google https://developers.google.com/speed/public-dns/
    208.67.222.222,208.67.220.220 OpenDNS https://www.opendns.com
    208.67.222.123,208.67.220.123 OpenDNS FamilyShield https://www.opendns.com
    9.9.9.9,149.112.112.112 Quad9 https://quad9.net
    77.88.8.8,77.88.8.1 Yandex https://dns.yandex.com
    77.88.8.88,77.88.8.2 Yandex Safe https://dns.yandex.com
    77.88.8.7,77.88.8.3 Yandex Family https://dns.yandex.com
    DNS servers for VPN users (default: 1.1.1.1,1.0.0.1): 176.103.130.130,176.103.130.131
    --- Configuration: general server settings ---
    Timezone (default: Europe/London): Email address for sysadmin (e.g. j.bloggs@example.com): me@my-domain.tld
    Desired SSH log-in port (default: 22): 2222
    New SSH log-in user name: george
    Copy /root/.ssh/authorized_keys to new user and disable SSH password log-in [Y/n]? y
    New SSH user's password (e.g. for sudo): Confirm new SSH user's password: 
  5. Once you're up and running, use these commands for some insight into what's going on:

     sudo ipsec statusall # status, who's connected, etc.
    sudo iptables -L -v # how much traffic has been forwarded, dropped, etc.?
    sudo tail -f /var/log/syslog # real-time logs of (dis)connections etc.
    

Troubleshooting

If things don't work out right away ...

  • On the client: make sure you created the connection using the newly emailed .mobileconfig file or PowerShell commands. Setting it up manually via the OS GUI will not work, since it will default to insecure ciphers which the server has not been configured to support. Also note that .mobileconfig files generated with earlier iterations of this script may no longer be compatible, since the configured ciphers have changed from time to time.

  • On the server: check that network ingress for UDP on ports 500 and 4500 is enabled (on some cloud platforms you'll have to add appropriate firewall rules to your virtual network). Also check that packet forwarding is enabled (on some cloud platforms this is controlled by a configuration setting that's off by default).

  • Check the server logs on strongSwan startup and when you try to connect, and the client logs when you try to connect.

    • On the server: Log in via SSH, then sudo tail -f /var/log/syslog. To see startup logs, log in to another session and sudo ipsec restart there, then switch back. To see what's logged during a connection attempt, try to connect from a client.

    • On the client: On a Mac, open Console.app in /Applications/Utilities. If connecting from an iPhone, plug the iPhone into the Mac. Pick the relevant device (in the bar down the left), filter the output (in the box at top right) to nesession, and try to connect. (On Windows or Linux I don't know where you find the logs — if you know, feel free to write the explanation and send a pull request).

  • The setup script is now more or less idempotent — you should be able to run it repeatedly with no ill effects — so, when you've fixed any issues, simply run it again.

  • If you have a tricky question about strongSwan, it's probably better to raise it with the strongSwan team than file an issue here.

Users

To add or change VPN users, it's:

 sudo nano /etc/ipsec.secrets

Edit usernames and passwords as you see fit (but don't touch the first line, which specifies the server certificate). The line format for each user is:

 someusername : EAP "somepassword"

To exit nano it's Ctrl + O then Ctrl + X, and to have strongSwan pick up the changes it's:

 sudo ipsec secrets

Upgrades

If you're on a pre-18.04 version of Ubuntu, it's probably easiest to make a record of any changes to ipsec.secrets, blow the whole thing away and reinstall, then reinstate ipsec.secrets.

Note that you may also need to delete and recreate all your client connection settings using the updated PowerShell commands or .mobileconfig file, since there have been a few cipher changes over time.

Bonus paranoia

Your traffic is not logged on the server, but if you're feeling especially paranoid there are various things you could do to reduce logging further. A simple and somewhat drastic option (once you've got everything working) is:

 sudo rm /var/log/syslog && sudo ln -s /dev/null /var/log/syslog
sudo rm /var/log/auth.log && sudo ln -s /dev/null /var/log/auth.log

Why?

We use a similar setup as a corporate VPN at PSYT. And I use this to bounce my personal web browsing via Europe, in the hope of giving Theresa May's Investigatory Powers Bill the finger.

Why IKEv2?

  • Fair security
  • Built-in clients for latest iOS, Mac and Windows (+ trustworthy free install on Android)
  • Connect on demand support on iOS and Mac
  • Robust to connection switching and interruptions via MOBIKE

More on IKEv2 at https://www.cl.cam.ac.uk/~mas90/resources/strongswan/ and https://www.bestvpn.com/blog/4147/pptp-vs-l2tp-vs-openvpn-vs-sstp-vs-ikev2/

Why not Algo?

Feel free to use Algo instead. It has similar aims, and now configures WireGuard too. However, it has many more moving parts, and requires several local installation steps before you even start setting up your VPN. This script is intended to be much simpler.

About

Set up Ubuntu Server 20.04 (or 18.04) as an IKEv2 VPN server

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages