Por que tudo isso e para quê?
Tínhamos: 10 configurações de servidor mais simples em DigitalOcean, dispositivos móveis iOS, um servidor para coleta de estatísticas, nenhuma experiência em configurar servidores VPN e um desejo indomável de fazer um serviço VPN rápido, confiável e fácil de usar que irá desfrutar aproveitar. Não que tudo isso fosse absolutamente necessário, mas se já começamos, devemos abordar o assunto com seriedade.
Neste artigo, descreverei brevemente como escolhemos o protocolo VPN, como configuramos o servidor e como organizamos a coleta de estatísticas de cada servidor VPN. Não confie em instruções detalhadas passo a passo. No artigo, fornecerei trechos dos arquivos de configuração com breves comentários.
Acho que na esfera de TI você não encontrará mais uma pessoa que não saiba o que é VPN e por que você precisa dela.
Mas se for uma tese para explicar por que uma pessoa moderna precisa de uma VPN, então algo como isto resultará:
- Se você tiver recursos internos (privados), o acesso aos quais deve ser limitado a partir da Internet global.
- Se você precisar estabelecer uma conexão segura entre duas redes.
- Se você precisar acessar recursos que, por um motivo ou outro, não estão disponíveis em seu país (sua localização muda em relação ao seu endereço IP).
E o ponto não totalmente óbvio: a velocidade da conexão com a Internet pode ser maior por meio de VPN, porque seu ISP pode enviar seu tráfego por uma rota mais curta, o que significa uma rota mais ideal, por isso, você pode obter um aumento na velocidade. Mas pode funcionar na direção oposta se você escolher um local de servidor não muito bom em relação a você (mais sobre isso mais tarde).
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 .
?
Por tentativa e erro, encontramos a opção descrita no artigo, antes de tudo aderimos ao princípio de "torná-lo mais simples", não reinventamos nossas próprias bicicletas e usamos ferramentas prontas como Docker, FreeRadius. Sim, muito provavelmente há um lugar para otimização, políticas de segurança mais rígidas e automação. Mas nossa opção é perfeita para uso pessoal e para uso em pequenas empresas se você precisar organizar o acesso a informações privadas (fechadas).