¿Por qué todo esto y para qué?
Teníamos: 10 configuraciones de servidor más simples en DigitalOcean, dispositivos móviles iOS, un servidor para recopilar estadísticas, ninguna experiencia en la configuración de servidores VPN y un deseo indomable de hacer un servicio VPN rápido, confiable y fácil de usar que disfrutará disfrutar. No es que todo esto sea absolutamente necesario, pero si ya hemos comenzado, entonces debemos abordar el asunto con seriedad.
En este artículo, describiré brevemente cómo elegimos el protocolo VPN, cómo configuramos el servidor y cómo organizamos la recopilación de estadísticas de cada servidor VPN. No confíe en instrucciones detalladas paso a paso. En el artículo, proporcionaré extractos de los archivos de configuración con breves comentarios.
Creo que en el ámbito de las TI ya no encontrarás una persona que no sepa qué es una VPN y por qué la necesitas.
Pero si es una tesis para explicar por qué una persona moderna necesita una VPN, entonces resultará algo como esto:
- Si tiene recursos internos (privados), el acceso a ellos debe estar limitado desde Internet global.
- Si necesita establecer una conexión segura entre dos redes.
- Si necesita acceder a recursos que, por una razón u otra, no están disponibles en su país (su ubicación cambia en relación con su dirección IP).
Y el punto no del todo obvio: la velocidad de la conexión a Internet puede ser mayor a través de vpn, porque su ISP puede enviar su tráfico por una ruta más corta, lo que significa una ruta más óptima, debido a esto, puede obtener un aumento de velocidad. Pero puede funcionar en la dirección opuesta si elige una ubicación de servidor no muy buena en relación con usted (más sobre eso más adelante).
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-.
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.
:
#!/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 .
?
A través de prueba y error, se nos ocurrió la opción descrita en el artículo, en primer lugar nos adherimos al principio de "hacerlo más simple", no reinventamos nuestras propias bicicletas y usamos herramientas listas para usar como Docker, FreeRadius. Sí, lo más probable es que haya un lugar para la optimización, el endurecimiento de las políticas de seguridad, la automatización. Pero nuestra opción es perfecta para uso personal y para uso en pequeñas empresas si necesita organizar el acceso a información privada (cerrada).