1. Устанавливаем Strongswan на FreeBSD, компилируем ядро с поддержкой IPsec. Устанавливаем на Android Strongswan из Google Play.2. Создаём сертификаты. Сначала ключ и сертификат CA:
openssl genrsa -out ipsec-test_CA_key.pem -aes256 -passout stdin 2048
openssl req -x509 -new -sha512 -days 3652 -set_serial 0 -out ipsec-test_CA.pem \
-key ipsec-test_CA_key.pem -passin stdin -passout stdin -verbose \
-subj "/C=RU/ST=My state/L=My city/O=My IT Lab/OU=My CA dept\
/CN=My personal CA/emailAddress=me@mymailhost"
3. После этого в /etc/ssl/openssl.cnf находим секцию "[usr_cert]" и добавляем строку с именем своего хоста:
subjectAltName = DNS:ipsec-test.dyndns.org
Это должно быть реально существующее DNS-имя - по нему Android будет находить стационарный хост. В данном случае, когда провайдер назначает на внешний интерфейс модема/роутера динамический "белый" IP-адрес, используется имя на бесплатном сервисе dyndns.org. С другими провайдерами возможны какие-то другие варианты.
Создаём сертификат стационарного хоста (поскольку это первый сертификат нашего CA, указываем параметр -CAcreateserial)
openssl genrsa -out 'ipsec-test.dyndns.org_key.pem' 2048
openssl req -new -sha512 -days 3652 -out 'ipsec-test.dyndns.org_req.pem' \
-key 'ipsec-test.dyndns.org_key.pem' -passin stdin -passout stdin \
-subj "/C=RU/ST=My state/L=My city/O=My IT Lab/OU=My CA dept\
/CN=ipsec-test.dyndns.org/subjectAltName=DNS:ipsec-test.dyndns.org\
/emailAddress=me@mymailhost"
openssl x509 -req -sha512 -days 3652 -extfile /etc/ssl/openssl.cnf \
-extensions "usr_cert" -CA ipsec-test_CA.pem -CAkey ipsec-test_CA_key.pem \
-CAcreateserial -CAserial ipsec-test_CA_serial \
-in 'ipsec-test.dyndns.org_req.pem' -out 'ipsec-test.dyndns.org_cert.pem'
Строго говоря, указывать параметр "subjectAltName=DNS:ipsec-test.dyndns.org" в строке subject не обязательно, значение имеет расширение x.509v3, заданное в openssl.cnf. В строку subject этот параметр добавлен для красоты, на самом деле ;).
Проверяем сертификат:
openssl x509 -in ipsec-test.dyndns.org_cert.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
8a:55:5e:dd:bb:22:20:cc
Signature Algorithm: sha512WithRSAEncryption
Issuer: C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, CN=My personal CA/emailAddress=me@mymailhost
Validity
Not Before: Oct 14 23:13:38 2013 GMT
Not After : Oct 14 23:13:38 2023 GMT
Subject: C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept,
CN=ipsec-test.dyndns.org/subjectAltName=DNS:ipsec-test.dyndns.org/emailAddress=me@mymailhost
(...)
[]X509v3 Subject Alternative Name:
DNS:ipsec-test.dyndns.org[]
(...)
4. Теперь создадим ключ и сертификат для мобильного устройства. Вообще-то, параметр "subjectAltName" в openssl.cnf можно теперь не указывать (закомментировать) - это связано с тем, что мобильный Strongswan в качестве своего ID передаёт строку subject своего сертификата (при том, что сам требует от партнёра ID, совпадающий с FQDN или IP-адресом). Всё же для соблюдения единообразия зададим в openssl.cnf "subjectAltName = DNS:android" и сгенерируем сертификат:
openssl genrsa -out android_key.pem 2048
openssl req -new -sha512 -days 3652 -out android_req.pem \
-key android_key.pem -passin stdin -passout stdin \
-subj "/C=RU/ST=My state/L=My city/O=My IT Lab/OU=My CA dept\
/CN=android/subjectAltName=DNS:android/emailAddress=me@mymailhost"
Проверяем сертификат:
openssl x509 -in android_cert.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
8a:55:5e:dd:bb:22:20:cd
Signature Algorithm: sha512WithRSAEncryption
Issuer: C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept,
CN=My personal CA/emailAddress=me@mymailhost
Validity
Not Before: Oct 15 19:58:45 2013 GMT
Not After : Oct 15 19:58:45 2023 GMT
[]Subject: C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, CN=android/subjectAltName=DNS:android
/emailAddress=me@mymailhost[]
(...)
Теперь преобразуем сертификат в формат PKCS#12:
openssl pkcs12 -export -out android_cert.p12 -in android_cert.pem \
-inkey android_key.pem -name Android -passout stdin -passin stdin
5. Конвертируем сертификаты и ключи в формат DER (в debug-выводе charon присутствуют жалобы на плагин PEM, поэтому не будем пользоваться форматом PEM):
openssl x509 -in ipsec-test_CA.pem -out ipsec-test_CA.der -inform pem -outform der
openssl rsa -in ipsec-test.dyndns.org_key.pem -out ipsec-test.dyndns.org_key.der -inform pem -outform der
openssl x509 -in ipsec-test.dyndns.org_cert.pem -out ipsec-test.dyndns.org_cert.der -inform pem -outform der
openssl x509 -in android_cert.pem -out android_cert.der -inform pem -outform
Создаём ссылку:
ln -s /etc/ssl/certs/ipsec-test/ipsec-test_CA.der /usr/local/etc/ipsec.d/cacerts
6. Создаём файл конфигурации ipsec.conf:
# ipsec.conf - strongSwan IPsec configuration file
config setup
# strictcrlpolicy=no
# uniqueids = yes
ca ipsec-test
cacert = /etc/ssl/certs/ipsec-test/ipsec-test_CA.der
conn android
keyexchange = ikev2
ike = AES_CBC_256-HMAC_SHA2_512-MODP4096
esp = AES_CBC_256-HMAC_SHA2_256
type = tunnel
leftsourceip = 192.168.254.1
rightsourceip = 192.168.254.2
auto = start
leftauth = pubkey
rightauth = pubkey
left = 192.168.203.3
right = %any
leftsubnet = 192.168.203.3
leftca = "C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, CN=My personal CA/emailAddress=me@mymailhost"
rightca = "C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, CN=My personal CA/emailAddress=me@mymailhost"
leftcert = /etc/ssl/certs/ipsec-test/ipsec-test.dyndns.org_cert.der
rightcert = /etc/ssl/certs/ipsec-test/android_cert.der
leftid = "ipsec-test.dyndns.org"
rightid = " C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, CN=android/subjectAltName=DNS:android/emailAddress=me@mymailhost"
7. Создаём файл ipsec.secrets:
"ipsec-test.dyndns.org" : RSA /etc/ssl/certs/ipsec-test/ipsec-test.dyndns.org_key.der
8. Устанавливаем сертификаты на мобильное устройство. Копируем сертификат android_cert.p12 и сертификат УЦ ipsec-test_CA.crt (сменив расширение .pem на .crt - это существенно) в корень SD-карты мобильного устройства.
Устанавливаем сертификаты: Настройки -> Безопасность -> Установить из памяти (Для сертификата в формате PKCS#12 надо буде ввести пароль, заданный в п.4).
9. Настраиваем мобильный Strongswan. В качестве шлюза задаём FQDN стационарного хоста ipsec-test.dyndns.org (оно же будет и "peer ID"), тип - IKEv2 Сертификат, выбираем загруженный и установленный сертификат мобильного устройства, указываем вручную сертификат нашего УЦ ([[http://www.ljplus.ru/img4/s/o/some_wise_man/20131017_ipsec07... скриншот]]).
10. Сохраняем, устанавливаем соединение. Вуаля!
11. Проверяем состояние стационарного хоста (да, утилита setkey - это из racoon, но я к ней привык ;)):
setkey -D
192.168.203.3 XXX.XXX.XXX.XXX
esp mode=tunnel spi=3944322401(0xeb199561) reqid=1(0x00000001)
E: rijndael-cbc 7b45804f 3e75bd59 7092e7ac dae00600
A: hmac-sha1 ec42cbbf e49848a9 72620762 bc97d0cb 6bfb8412
seq=0x00000000 replay=32 flags=0x00000000 state=mature
created: Oct 17 17:29:48 2013 current: Oct 17 17:30:05 2013
diff: 17(s) hard: 3600(s) soft: 2957(s)
last: hard: 0(s) soft: 0(s)
current: 0(bytes) hard: 0(bytes) soft: 0(bytes)
allocated: 0 hard: 0 soft: 0
sadb_seq=1 pid=902 refcnt=1
XXX.XXX.XXX.XXX 192.168.203.3
esp mode=any spi=3276763214(0xc34f704e) reqid=1(0x00000001)
E: rijndael-cbc 70c5b1df dc0932a9 d8c8558b bd44caf7
A: hmac-sha1 f3161cbc 50952da1 c298b3af 77008587 8bbc4f1f
seq=0x00000000 replay=32 flags=0x00000000 state=mature
created: Oct 17 17:29:48 2013 current: Oct 17 17:30:05 2013
diff: 17(s) hard: 3600(s) soft: 2560(s)
last: hard: 0(s) soft: 0(s)
current: 0(bytes) hard: 0(bytes) soft: 0(bytes)
allocated: 0 hard: 0 soft: 0
sadb_seq=0 pid=902 refcnt=1
setkey -DP
192.168.254.2[any] 192.168.203.3[any] any
in ipsec
esp/tunnel/XXX.XXX.XXX.XXX-192.168.203.3/unique:1
created: Oct 17 17:29:48 2013 lastused: Oct 17 17:29:48 2013
lifetime: 2147483647(s) validtime: 0(s)
spid=4 seq=1 pid=917
refcnt=1
192.168.203.3[any] 192.168.254.2[any] any
out ipsec
esp/tunnel/192.168.203.3-XXX.XXX.XXX.XXX/unique:1
created: Oct 17 17:29:48 2013 lastused: Oct 17 17:29:48 2013
lifetime: 2147483647(s) validtime: 0(s)
spid=3 seq=0 pid=917
refcnt=1
XXX.XXX.XXX.XXX - IP-адрес внешнего интерфейса шлюза провайдера (трафик проходит через NAT).
В одной консоли запускаем "tcpdump -i ep1 -n host XXX.XXX.XXX.XXX", в другой - "ping 192.168.254.2":
tcpdump -i ep1 -n host XXX.XXX.XXX.XXX
listening on ep1, link-type EN10MB (Ethernet), capture size 65535 bytes
17:34:49.316449 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: isakmp-nat-keep-alive
17:34:50.578734 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: isakmp-nat-keep-alive
17:35:06.825124 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x1), length 132
17:35:07.826283 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x2), length 132
17:35:08.827392 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x3), length 132
17:35:09.094268 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x1), length 132
17:35:09.154359 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x2), length 132
17:35:09.194508 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x3), length 132
17:35:09.828539 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x4), length 132
17:35:09.953676 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x4), length 132
17:35:10.503650 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: isakmp-nat-keep-alive
17:35:10.829664 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x5), length 132
17:35:10.954139 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x5), length 132
17:35:30.327819 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: isakmp-nat-keep-alive
17:35:31.118437 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: isakmp-nat-keep-alive
17:35:50.332414 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: isakmp-nat-keep-alive
17:35:52.174896 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: isakmp-nat-keep-alive
URL: http://some-wise-man.livejournal.com/232203.html
Обсуждается: http://www.opennet.dev/tips/info/2808.shtml