robonuka/strongswan

By robonuka

Updated about 1 month ago

Alpine Edge + Strongswan 6.0.6 IKEv2 EAP-MSCHAPv2 + Server's Letsencrypt SSL certificate

Image
Security
4

3.8K

robonuka/strongswan repository overview

Do these steps BEFORE Strongswan server first run

  1. Create DNS 'A'-record for your your.vpn.server.fqdn and check that it is successfully resolved from the Internet

  2. Prepare folders structure for the Strongswan, frontend Nginx and Letsencrypt issuer/updater containers:

mkdir -p /opt/strongswan
mkdir -p /opt/nginx-proxy/{acme.sh,certs,conf.d,html,htpasswd,logs,vhost.d}
  1. Generate file '/opt/nginx-proxy/dhparam.pem' with this command:
openssl dhparam -out /opt/nginx-proxy/dhparam.pem 2048
  1. Create /opt/docker-compose.yml file: (do not forget to replace your.vpn.server.fqdn and [email protected] with YOUR values)
services:
  nginx-proxy:
    container_name: nginx-proxy
    image: jwilder/nginx-proxy
    restart: unless-stopped
    ports:
      - 80:80/tcp
      - 443:443/tcp
    volumes:
      - /opt/nginx-proxy/certs:/etc/nginx/certs
      - /opt/nginx-proxy/conf.d:/etc/nginx/conf.d
      - /opt/nginx-proxy/html:/usr/share/nginx/html
      - /opt/nginx-proxy/vhost.d:/etc/nginx/vhost.d
      - /opt/nginx-proxy/dhparam.pem:/etc/nginx/dhparam/dhparam.pem
      - /etc/localtime:/etc/localtime
      - /etc/timezone:/etc/timezone
      - /var/run/docker.sock:/tmp/docker.sock:ro
    networks:
      - mynetwork
  nginx-proxy-le:
    container_name: nginx-proxy-le
    image: jrcs/letsencrypt-nginx-proxy-companion
    restart: unless-stopped
    environment:
      - "NGINX_PROXY_CONTAINER=nginx-proxy"
    volumes:
      - /etc/localtime:/etc/localtime
      - /etc/timezone:/etc/timezone
      - /opt/nginx-proxy/acme.sh:/etc/acme.sh
      - /opt/nginx-proxy/certs:/etc/nginx/certs
      - /opt/nginx-proxy/vhost.d:/etc/nginx/vhost.d
      - /opt/nginx-proxy/html:/usr/share/nginx/html
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - mynetwork
  strongswan-le:
    container_name: strongswan-le
    image: robonuka/le-cert-issuer
    restart: unless-stopped
    init: true
    depends_on:
      - nginx-proxy-le
    expose:
      - 80/tcp
    environment:
      - "VIRTUAL_HOST=your.vpn.server.fqdn"
      - "VIRTUAL_PORT=80"
      - "LETSENCRYPT_HOST=your.vpn.server.fqdn"
      - "[email protected]"
      - "LETSENCRYPT_RESTART_CONTAINER=true"
      - "SLAVE_CONTAINER_NAME=strongswan"
      - "DOCKER_SOCKET_FILE=/tmp/docker.sock"
    volumes:
      - /etc/localtime:/etc/localtime
      - /var/run/docker.sock:/tmp/docker.sock:ro
    networks:
      - mynetwork
networks:
    mynetwork:
      driver: 'bridge'
  1. Generate Strongswan server's key and SSL-certificate file for the first time:
docker compose up -d nginx-proxy nginx-proxy-le strongswan-le
  1. Wait for the .PEM-files appear in the /opt/nginx-proxy/certs/your.vpn.server.fqdn folder:
cert.pem
chain.pem
fullchain.pem
key.pem

If .PEM-files are absent there after 30-40 seconds - try to restart strongswan-le container
and see the logs of the nginx-proxy-le container to get the reason of .PEM-files are absent

docker compose restart strongswan-le && docker logs -f nginx-proxy-le

IMPORTANT: Anyway, YOU DO NEED to get the correct .PEM-files BEFORE doing the final step !!!

The final step:

  • Add strongswan: section to the /opt/docker-compose.yml file:
    (default values of IKE and ESP variables you can see below in this example)
  strongswan:
    container_name: strongswan
    image: robonuka/strongswan:latest
    restart: unless-stopped
    init: true
    network_mode: "host"
    privileged: yes
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
      - SYS_ADMIN
    environment:
      - "CHARONDEBUG=dmn -1, mgr -1, ike 1, chd -1, job -1, cfg -1, knl 1, net 1, asn -1, enc -1, lib -1, esp 1, tls -1, tnc -1, imc -1, imv -1, pts -1"
      - "IKE=aes128-sha1-modp1024,aes128-sha1-modp1536,aes128-sha1-modp2048,aes128-sha256-ecp256,aes128-sha256-modp1024,aes128-sha256-modp1536,aes128-sha256-modp2048,aes256-aes128-sha256-sha1-modp2048-modp4096-modp1024,aes256-sha1-modp1024,aes256-sha256-modp1024,aes256-sha256-modp1536,aes256-sha256-modp2048,aes256-sha256-modp4096,aes256-sha384-ecp384,aes256-sha384-modp1024,aes256-sha384-modp1536,aes256-sha384-modp2048,aes256-sha384-modp4096,aes256gcm16-aes256gcm12-aes128gcm16-aes128gcm12-sha256-sha1-modp2048-modp4096-modp1024,aes256gcm16-prfsha256-ecp521,aes256-sha256-ecp384,3des-sha1-modp1024!"
      - "ESP=aes128-aes256-sha1-sha256-modp2048-modp4096-modp1024,aes128-sha1,aes128-sha1-modp1024,aes128-sha1-modp1536,aes128-sha1-modp2048,aes128-sha256,aes128-sha256-ecp256,aes128-sha256-modp1024,aes128-sha256-modp1536,aes128-sha256-modp2048,aes128gcm12-aes128gcm16-aes256gcm12-aes256gcm16-modp2048-modp4096-modp1024,aes128gcm16,aes128gcm16-ecp256,aes256-sha1,aes256-sha256,aes256-sha256-modp1024,aes256-sha256-modp1536,aes256-sha256-modp2048,aes256-sha256-modp4096,aes256-sha384,aes256-sha384-ecp384,aes256-sha384-modp1024,aes256-sha384-modp1536,aes256-sha384-modp2048,aes256-sha384-modp4096,aes256gcm16,aes256gcm16-ecp384,3des-sha1!"
      - "SERVER_IP=your.vpn.server.ip"                                 # Default: %any
      - "SERVER_HOSTNAME=your.vpn.server.fqdn"                         # Default: vpn.example.com
      - "SERVER_SUBNET=A.B.C.D/CIDR"                                   # Default: 0.0.0.0/0"
      - "CLIENT_SUBNET=E.F.G.H/CIDR"                                   # Default: 10.10.10.0/24
      - "CLIENT_DNS=I.J.K.L,M.N.O.P"                                   # Default: 8.8.8.8,8.8.4.4
      - "USERS=user1:pass1 user2:pass2 user3:pass3 userN:passN"        # Space separated 'login:password' couples
    volumes:
      - /etc/localtime:/etc/localtime
      - /opt/nginx-proxy/certs/your.vpn.server.fqdn/chain.pem:/etc/ipsec.d/cacerts/ca.pem:ro
      - /opt/nginx-proxy/certs/your.vpn.server.fqdn/cert.pem:/etc/ipsec.d/certs/certificate.pem:ro
      - /opt/nginx-proxy/certs/your.vpn.server.fqdn/key.pem:/etc/ipsec.d/private/key.pem:ro
      - /opt/strongswan:/mnt

Or you can configure Strongswan to use your own ipsec.conf and ipsec.secrets files with SERVER_MODE variable = MANUAL

  strongswan:
    container_name: strongswan
    image: robonuka/strongswan:latest
    restart: unless-stopped
    init: true
    network_mode: "host"
    privileged: true
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
      - SYS_ADMIN
    environment:
      - "SERVER_MODE=MANUAL"
    volumes:
      - /etc/localtime:/etc/localtime
      - /opt/nginx-proxy/certs/your.vpn.server.fqdn/chain.pem:/etc/ipsec.d/cacerts/ca.pem:ro
      - /opt/nginx-proxy/certs/your.vpn.server.fqdn/cert.pem:/etc/ipsec.d/certs/certificate.pem:ro
      - /opt/nginx-proxy/certs/your.vpn.server.fqdn/key.pem:/etc/ipsec.d/private/key.pem:ro
      - /opt/strongswan/mobileconfig:/mnt
      - /opt/strongswan/ipsec.conf:/etc/ipsec.conf
      - /opt/strongswan/ipsec.secrets:/etc/ipsec.secrets

In this case you should prepare the correct ipsec.conf and ipsec.secrets files by yourself
SERVER_MODE=MANUAL will be useful if you need to establish some P2P tunnels in additional to simple VPN-clients connections.

START 'strongswan' container:

docker compose up -d strongswan

Then get username.mobileconfig files from the /opt/strongswan folder.

IMPORTANT: If you use SERVER_MODE=MANUAL variable

  1. There are NO .mobileconfig files will be auto generated
    You shoud run this command manually if you want to get them: docker exec strongswan /mobileconfig
    Then look at the "/mnt" folder inside container
  2. There are NO iptables rules will be auto added
    You should care about iptables rules by yourself!

Autorenew Letsencrypt SSL-certificate procedure

Don't care about that. Container strongswan-le doing that automatically.

Tag summary

Content type

Image

Digest

sha256:ad7973b29

Size

28 MB

Last updated

about 1 month ago

docker pull robonuka/strongswan