Pisałem, że namęczyłem się, żeby odpalić L2TP/IPsec między PLD i Androidem.
Napisałem też, że taki tunel nie zupełnie jest bezpieczny
I co? Zrezygnować z tego IPsec i VPN w ogóle? Czy może kombinować z innym rozwiązaniem? A może jednak załatać tego IPSec?
Wybrałem trzecią opcję. Jeśli chodzi o sprawdzanie certyfikatu, to obejście problemu już opisałem – trzeba zrobić własne CA, które wystawi jeden certyfikat, dla serwera.
Drugi problem (10 sekund plain tekstu) nie da się obejść po stronie serwera, ale da się coś zrobić na telefonie. Na zrootowanym telefonie na pewno.
Okazało się, że na kernel w telefonie posiada pełnosprawny podsystem netfilter i za pomocą iptables można zablokować nieszyfrowany ruch. Używam już Droidwalla, więc wystarczyło dołożyć mu kilka regułek.
No to, po kolei:
Stworzenie prostego CA:
cat >ca.cnf <<EOF
[ req ]
default_bits = 2048
default_keyfile = ca-key.pem
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
string_mask = nombstr
attributes = req_attributes
prompt = no
[ req_attributes ]
[ req_distinguished_name ]
commonName = VPN CA
[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = CA:true
EOF
openssl req -new -x509 -config ca.cnf -batch -nodes -days 3650 -out ca-cert.pem
Za pomocą tego CA tworzę certyfikat dla serwera (sensowne subjectName i subjectAltName na wypadek jakbym czymś normalnym też chciał się łączyć, bo Android ma to w nosie):
cat >vpn.cnf <<EOF
[ req ]
default_bits = 2048
default_keyfile = vpn-key.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
prompt = no
[ req_distinguished_name ]
commonName = vpn.example.org
[ req_attributes ]
subjectAltName=IP:10.20.30.40;DNS:vpn.example.org
[ cert ]
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment, keyAgreement
EOF
openssl req -new -batch -nodes -config vpn.cnf -out vpn-req.pem
openssl x509 -req -in vpn-req.pem -CA ca-cert.pem -CAkey ca-key.pem -set_serial $RANDOM -out vpn-cert.pem
vpn-key.pem
i vpn-cert.pem
wrzucam do konfiguracji Racoona. ca-cert.pem
trzeba zainstalować na telefonie – ja wrzuciłem na swój serwer WWW, pod nazwą ca-cert.crt
i załadowałem przeglądarką z telefonu. Potem trzeba wybrać to zaimportowane CA w konfiguracji łącza VPN. Należy pamiętać, że nie wolno tego samego CA używać do wystawiania certyfikatów klientów, ani najlepiej żadnych innych.
Teraz blokowanie plaintekstu… Wchodzę do DroidWall, tam z menu wybieram więcej/Set custom script i wklejam następujące skrypty:
# allow Android only to connect to L2TP over ipsec
$IPTABLES -A "droidwall" -m udp -p 17 --dport 1701 -m policy --pol ipsec --dir out -j ACCEPT
$IPTABLES -A "droidwall" -m udp -p 17 --dport 1701 -j DROP
# prevent injection of unauthenticated packets
$IPTABLES -F INPUT
$IPTABLES -A INPUT -m udp -p 17 --sport 1701 -m policy --pol ipsec --dir in -j ACCEPT
$IPTABLES -A INPUT -m udp -p 17 --sport 1701 -j DROP
oraz (shutdown script):
# clean the rules added to INPUT
$IPTABLES -F INPUT
I to by było na tyle.