Wie wir das VPN-Protokoll ausgewählt und den Server eingerichtet haben

Warum das alles und wofür?



Wir hatten: 10 einfachste Serverkonfigurationen auf DigitalOcean, iOS-Mobilgeräten, einen Server zum Sammeln von Statistiken, keine Erfahrung beim Einrichten von VPN-Servern und den unbezwingbaren Wunsch, einen schnellen, zuverlässigen und benutzerfreundlichen VPN-Dienst zu erstellen, der Spaß macht genießen. Nicht, dass dies alles absolut notwendig gewesen wäre, aber wenn wir bereits begonnen haben, müssen wir uns der Sache ernsthaft nähern.



In diesem Artikel werde ich kurz beschreiben, wie wir das VPN-Protokoll ausgewählt haben, wie wir den Server eingerichtet haben und wie wir die Erfassung von Statistiken von jedem VPN-Server organisiert haben. Verlassen Sie sich nicht auf detaillierte Schritt-für-Schritt-Anleitungen. In diesem Artikel werde ich Auszüge aus den Konfigurationsdateien mit kurzen Kommentaren versehen.



Ich denke, dass Sie im IT-Bereich keine Person mehr finden werden, die nicht weiß, was ein VPN ist und warum Sie es brauchen.



Aber wenn es eine These ist, zu erklären, warum ein moderner Mensch ein VPN braucht, dann wird sich so etwas herausstellen:



  • Wenn Sie über interne (private) Ressourcen verfügen, sollte der Zugriff über das globale Internet eingeschränkt werden.
  • Wenn Sie eine sichere Verbindung zwischen zwei Netzwerken herstellen müssen.
  • Wenn Sie auf Ressourcen zugreifen müssen, die aus dem einen oder anderen Grund in Ihrem Land nicht verfügbar sind (Ihr Standort ändert sich relativ zu Ihrer IP-Adresse).


Und der nicht ganz offensichtliche Punkt: Die Geschwindigkeit der Internetverbindung kann durch VPN höher sein, weil Ihr ISP kann Ihren Datenverkehr auf einer kürzeren Route senden, was eine optimalere Route bedeutet. Dadurch können Sie die Geschwindigkeit erhöhen. Es kann jedoch in die entgegengesetzte Richtung funktionieren, wenn Sie einen nicht sehr guten Serverstandort in Bezug auf Sie auswählen (dazu später mehr).



VPN-



VPN- .



.



, :



  • .
  • .


+ , .



PPTP (Point-To-Point Tunneling Protocol)



VPN , Microsoft. - , . Microsoft L2TP SSTP PPTP.



, .



L2TP/IPSec



PPTP, . , -, .. .

L2TP/IPsec , . : , , VPN-.



.. , , , .



IKEv2/IPSec



Microsoft Cisco, (, OpenIKEv2, Openswan strongSwan).



Mobility and Multi-homing Protocol (MOBIKE), .



IKEv2 , WiFi .



IKEv2 .



, .. Mobility and Multi-homing Protocol .



OpenVPN



OpenVPN Technologies.



, .

OpenVPN . , TCP UPD, . VPN .



OpenVPN, , .



, , , - , .



Wireguard



VPN. IPSec OpenVPN, , , .



Unix , .. Unix. .



, , .



.



IKEv2/IPSe, :



  • Mobility and Multi-homing Protocol (MOBIKE).
  • .
  • .
  • .


.



VPN-



, , () ().



— , .. , ( ), .., , - .



- , digitalocean , 1 Gb 25 Gb .



, - VPN- .



:



  • Docker + docker-compose.
  • strongswan — IPSec .
  • Let's Encrypt — .
  • Radius — .


Docker , vpn-.



Docker.file ( )



FROM alpine:latest #      alpine-linux

...
# strongSwan Version
ARG SS_VERSION="https://download.strongswan.org/strongswan-5.8.2.tar.gz" #   ,        .

...

COPY ./run.sh /run.sh
COPY ./adduser.sh /adduser.sh
COPY ./rmuser.sh /rmuser.sh

RUN chmod 755 /run.sh /adduser.sh /rmuser.sh

VOLUME ["/usr/local/etc/ipsec.secrets"]

EXPOSE 500:500/udp 4500:4500/udp

CMD ["/run.sh"]


adduser.sh, rmuser.sh .



adduser.sh



#!/bin/sh

VPN_USER="$1"

if [ -z "$VPN_USER" ]; then
  echo "Usage: $0 username" >&2
  echo "Example: $0 jordi" >&2
  exit 1
fi

case "$VPN_USER" in
  *[\\\"\']*)
    echo "VPN credentials must not contain any of these characters: \\ \" '" >&2
    exit 1
    ;;
esac

VPN_PASSWORD="$(openssl rand -base64 9)" #   
HOST="$(printenv VPNHOST)"

echo "Password for user is: $VPN_PASSWORD"
echo $VPN_USER : EAP \"$VPN_PASSWORD\">> /usr/local/etc/ipsec.secrets #        /usr/local/etc/ipsec.secrets

ipsec rereadsecrets


rmuser.sh



#!/bin/sh

VPN_USER="$1"

if [ -z "$VPN_USER" ]; then
  echo "Usage: $0 username" >&2
  echo "Example: $0 jordi" >&2
  exit 1
fi

cp /usr/local/etc/ipsec.secrets /usr/local/etc/ipsec.secrets.bak
sed "/$VPN_USER :/d" /usr/local/etc/ipsec.secrets.bak > /usr/local/etc/ipsec.secrets #        /usr/local/etc/ipsec.secrets

ipsec rereadsecrets


ipsec.secrets.



:



run.sh



#!/bin/bash

VPNIPPOOL="10.15.1.0/24" #       IP  ,     VPN-.
LEFT_ID=${VPNHOST}       #   vpn-

sysctl net.ipv4.ip_forward=1
sysctl net.ipv6.conf.all.forwarding=1
sysctl net.ipv6.conf.eth0.proxy_ndp=1

if [ ! -z "$DNS_SERVERS" ] ; then #    DNS ,     vpn .
DNS=$DNS_SERVERS
else
DNS="1.1.1.1,8.8.8.8"
fi

if [ ! -z "$SPEED_LIMIT" ] ; then #  ,     ""  ,       .
tc qdisc add dev eth0 handle 1: ingress
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip src 0.0.0.0/0 police rate ${SPEED_LIMIT}mbit burst 10k drop flowid :1
tc qdisc add dev eth0 root tbf rate ${SPEED_LIMIT}mbit latency 25ms burst 10k
fi

iptables -t nat -A POSTROUTING -s ${VPNIPPOOL} -o eth0 -m policy --dir out --pol ipsec -j ACCEPT
iptables -t nat -A POSTROUTING -s ${VPNIPPOOL} -o eth0 -j MASQUERADE

iptables -L

#     
if [[ ! -f "/usr/local/etc/ipsec.d/certs/fullchain.pem" && ! -f "/usr/local/etc/ipsec.d/private/privkey.pem" ]] ; then
    certbot certonly --standalone --preferred-challenges http --agree-tos --no-eff-email --email ${LEEMAIL} -d ${VPNHOST}
    cp /etc/letsencrypt/live/${VPNHOST}/fullchain.pem /usr/local/etc/ipsec.d/certs
    cp /etc/letsencrypt/live/${VPNHOST}/privkey.pem /usr/local/etc/ipsec.d/private
    cp /etc/letsencrypt/live/${VPNHOST}/chain.pem /usr/local/etc/ipsec.d/cacerts
fi

rm -f /var/run/starter.charon.pid

#   ipsec 
if [ -f "/usr/local/etc/ipsec.conf" ]; then
rm /usr/local/etc/ipsec.conf
cat >> /usr/local/etc/ipsec.conf <<EOF
config setup
    charondebug="ike 1, knl 1, cfg 1"
    uniqueids=never
    conn ikev2-vpn
    ...

    eap_identity=%identity
EOF
fi

if [ ! -f "/usr/local/etc/ipsec.secrets" ]; then
cat > /usr/local/etc/ipsec.secrets <<EOF
: RSA privkey.pem
EOF
fi

.....
EOF
fi
sysctl -p

ipsec start --nofork


, docker-compose:



version: '3'

services:
  vpn:
    build: .
    container_name: ikev2-vpn-server
    privileged: true
    volumes:
      - './data/certs/certs:/usr/local/etc/ipsec.d/certs'
      - './data/certs/private:/usr/local/etc/ipsec.d/private'
      - './data/certs/cacerts:/usr/local/etc/ipsec.d/cacerts'
      - './data/etc/ipsec.d/ipsec.secrets:/usr/local/etc/ipsec.secrets'
    env_file:
      - .env
    ports:
      - '500:500/udp'
      - '4500:4500/udp'
      - '80:80'
    depends_on:
      - radius
    links:
      - radius
    networks:
      - backend

  radius:
    image: 'freeradius/freeradius-server:latest'
    container_name: freeradius-server
    volumes:
      - './freeradius/clients.conf:/etc/raddb/clients.conf'
      - './freeradius/mods-enabled/rest:/etc/raddb/mods-enabled/rest'
      - './freeradius/sites-enabled/default:/etc/raddb/sites-enabled/default'
    env_file:
      - .env
    command: radiusd -X
    networks:
      - backend
networks:
  backend:
    ipam:
      config:
        - subnet: 10.0.0.0/24


volume , .



, , Let's Encrypt.



.env , :



VPNHOST=vpn.vpn.com #   vpn-
LEEMAIL=admin@admin.com #  ,       Let's Encrypt
SPEED_LIMIT=20 #  ,       mbit
DNS_SERVERS= #      DNS 
RADIUS_SERVER= #  radius ,      radius
RADIUS_SERVER_SECRET= #  ,       radius 
REMOTE_SERVER= #     endpoint,      radius ,    .


docker-compose up -d, vpn-, radius ( ).





VPN-



, , . ipsec, , - , .



, , FreeRadius , ipsec .



FreeRadius , .

radius ipsec:



FreeRADIUS



if [[ ! -z "$RADIUS_SERVER" && ! -z "$RADIUS_SERVER_SECRET" ]]; then
rm /usr/local/etc/strongswan.d/charon/eap-radius.conf
cat >> /usr/local/etc/strongswan.d/charon/eap-radius.conf <<EOF
eap-radius {
    accounting = yes #  , ipsec        /,        
    accounting_close_on_timeout = no
    accounting_interval = 300 #    radius     .
    close_all_on_timeout = no
    load = yes
    nas_identifier = $VPNHOST

    # Section to specify multiple RADIUS servers.
    servers {
        primary {
            address = $RADIUS_SERVER
            secret = $RADIUS_SERVER_SECRET
            auth_port = 1812   # default
            acct_port = 1813   # default
        }
    }
}


endpoint, rest. /etc/raddb/mods-enabled/rest accounting, - :



accounting {
    uri = "${..connect_uri}/vpn_sessions/%{Acct-Session-Id}-%{Acct-Unique-Session-ID}"
method = 'post'
tls = ${..tls}
body = json
data = '{ "username": "%{User-Name}", "nas_port": "%{NAS-Port}", "nas_ip_address": "%{NAS-IP-Address}", "framed_ip_address": "%{Framed-IP-Address}", "framed_ipv6_prefix": "%{Framed-IPv6-Prefix}", "nas_identifier": "%{NAS-Identifier}", "airespace_wlan_id": "%{Airespace-Wlan-Id}", "acct_session_id": "%{Acct-Session-Id}", "nas_port_type": "%{NAS-Port-Type}", "cisco_avpair": "%{Cisco-AVPair}", "acct_authentic": "%{Acct-Authentic}", "tunnel_type": "%{Tunnel-Type}", "tunnel_medium_type": "%{Tunnel-Medium-Type}", "tunnel_private_group_id": "%{Tunnel-Private-Group-Id}", "event_timestamp": "%{Event-Timestamp}", "acct_status_type": "%{Acct-Status-Type}", "acct_input_octets": "%{Acct-Input-Octets}", "acct_input_gigawords": "%{Acct-Input-Gigawords}", "acct_output_octets": "%{Acct-Output-Octets}", "acct_output_gigawords": "%{Acct-Output-Gigawords}", "acct_input_packets": "%{Acct-Input-Packets}", "acct_output_packets": "%{Acct-Output-Packets}", "acct_terminate_cause": "%{Acct-Terminate-Cause}", "acct_session_time": "%{Acct-Session-Time}", "acct_delay_time": "%{Acct-Delay-Time}", "calling_station_id": "%{Calling-Station-Id}", "called_station_id": "%{Called-Station-Id}"}'

 }


.



VPN , , Apple , , , Let's Encrypt.



?



  • radius , VPN.
  • , VPN-.


VPN-?



  • radius.
  • .
  • , .
  • health-check .


?



Durch Versuch und Irrtum kamen wir auf die im Artikel beschriebene Option. Zunächst hielten wir uns an das Prinzip "Einfacher machen", erfanden unsere eigenen Fahrräder nicht neu und verwendeten vorgefertigte Werkzeuge wie Docker, FreeRadius. Ja, höchstwahrscheinlich gibt es Raum für Optimierung, Verschärfung der Sicherheitsrichtlinien und Automatisierung. Unsere Option eignet sich jedoch perfekt für den persönlichen Gebrauch und für den Einsatz in kleinen Unternehmen, wenn Sie den Zugriff auf private (geschlossene) Informationen organisieren müssen.




All Articles