В статье рассказывается о том, что необходимо сделать, чтобы иметь на локальной машине интерфейс с белым IP даже если она находится за брандмауэром (корпоративным, например) или за http-proxy.
Для достижения цели понадобится сервер вне локальной сети с по крайней мере 1 физическим интерфейсом с белым IP и возможностью использовать второй белый IP (например, прописав алиас) из той же подсети (белой), что и первый.
Идея
Идея состоит в том, что на сервере создаётся tap-интерфейс с первым белым IP и сетевым мостом объединяется с физическим интерфейсом; на локальной машине создаётся tap-интерфейс со вторым белым IP и шлюзом из сети сервера и объединяется с tap-интерфейсом сервера с помощью openvpn. Далее только остаётся маршрутизировать на локальной машине первый белый IP на старый интерфейс, а весь остальной траффик на шлюз в сети сервера.
Конфигурация систем
Опишу конфигурацию, которая работает у меня. Уверен, можно создать то же самое и для Windows XP + Windows XP и для любых сочетаний Win2k+ и/или Linux.
Локальная машина — Windows 7 Ultimate c доступом локального администратора.
Удалённый сервер — Ubuntu-11.10-amd64-minimal с root-доступом (в реальности стоит на xen и имеет доступ к консоли по vnc). Имеет один физический интерфейс в «белой» подсети X.Y.Z.0/24 со шлюзом X.Y.Z.1 и возможность настроить любой из двух IP адресов (белых): либо X.Y.Z.100, либо X.Y.Z.200.
Конфигурация клиента
На Windows устанавливаем openvpn, который по умолчанию создаёт 1 TUN/TAP интерфейс.
Если необходимо шифрование траффика и авторизация по сертификатам, то создаём ключи/сертификаты (для сервера, для клиента (одного) и, если необходима HMAC, командой openvpn --genkey --secret ta.key один общий), как это описано здесь. Хочу заметить, что удобно для клиента использовать build-key-pkcs12.bat, а для сервера в файл build-key-server.bat добавить строку:
openssl pkcs12 -export -inkey %KEY_DIR%%1.key -in %KEY_DIR%%1.crt -certfile %KEY_DIR%ca.crt -out %KEY_DIR%%1.p12
Таким образом, в результате получаем pkcs12-файл для сервера server.p12.
pkcs12-файл клиента client.p12 и ta.key сохраняем куда-либо и в этой же папке создаём файл настроек client.ovpn:
dev tap
persist-tun
nobind
remote X.Y.Z.100 1194 udp
ifconfig X.Y.Z.200 255.255.255.0
ifconfig-nowarn
route-delay 10
route-gateway X.Y.Z.1
redirect-gateway def1
dhcp-option DNS 8.8.4.4
dhcp-option DNS 8.8.8.8
;route X.Y.Z.100 255.255.255.255 net_gateway
;route X.Y.Z.0 255.255.255.0 X.Y.Z.1
tls-client
tls-auth ta.key 1
pkcs12 client.p12
remote-cert-tls server
persist-key
keepalive 10 60
comp-lzo adaptive
verb 4
Если закомментировать блок с redirect-gateway и раскоментировать следующий блок, то траффик с локальной машины не будет заворачиваться на интерфейс с белым IP.
Конфигурация сервера
Сервер у меня арендованый (vdscom тариф с 2-мя IP).
На Ubuntu устанавливаем (удобно работать из-под root) openvpn, brctl:
apt-get update
apt-get install openvpn
apt-get install bridge-utils
Копируем server.p12, ta.key, dh2048.pem на сервер (удобно использовать WinSCP). На сервере создаём файлы bridge-start.sh, bridge-stop.sh как описано в статье ethernet-bridging.
Файл bridge-start.sh:
#!/usr/bin/env bash set -o errexit br="br0" tap="tap0" eth="eth0" eth_ip="X.Y.Z.100" eth_netmask="255.255.255.0" eth_broadcast="X.Y.Z.255" eth_gateway="X.Y.Z.1" modprobe tun for t in $tap; do openvpn --mktun --dev $t done brctl addbr $br brctl addif $br $eth for t in $tap; do brctl addif $br $t done for t in $tap; do ifconfig $t 0.0.0.0 promisc up done ifconfig $eth 0.0.0.0 promisc up ifconfig $br $eth_ip netmask $eth_netmask broadcast $eth_broadcast ip route add default via $eth_gateway
Файл bridge-stop.sh:
#!/usr/bin/env bash br="br0" tap="tap0" eth_gateway="X.Y.Z.1" ifconfig $br down brctl delbr $br for t in $tap; do openvpn --rmtun --dev $t done ip route add default via $eth_gateway
Если в сети X.Y.Z.0/24 присутствует DHCP-сервер, то файл /etc/network/interfaces должен выглядеть примерно так (eth0 должен быть не dhcp, а должен быть static, чтобы не получить постороннего IP-адреса в составе br0):
auto lo iface lo inet loopback allow-hotplug eth0 auto eth0 iface eth0 inet static address X.Y.Z.100 network X.Y.Z.0 netmask 255.255.255.0 broadcast X.Y.Z.255 gateway X.Y.Z.1
Создаём файл настроек сервера openvpn server.ovpn:
dev tap0
persist-tun
proto udp
lport 1194
local X.Y.Z.100
mode p2p
max-clients 1
tls-server
dh dh2048.pem
tls-auth ta.key 0
pkcs12 server.p12
persist-key
keepalive 10 60
comp-lzo adaptive
status openvpn-status.log
log-append openvpn.log
verb 3
mute 20
Заметьте, что сервер не имеет настройки ipconfig на tap-интерфейсе.
Эксплуатация
Запуск
Создаём и настраиваем сетевой мост и шлюз:
. bridge-start.sh
Запускаем сервер openvpn:
openvpn --daemon --config server.ovpn
Запускаем клиент.
Проверка
Проверяем с клиента всё ли правильно (в выводе команды первым должен быть X.Y.Z.1):
tracert 8.8.8.8
Запускаем iperf-сервер:
iperf -s
и просим, например, друга выполнить с его машины
iperf -c X.Y.Z.200
Останов
Останавливаем клиент.
На сервере выполняем:
killall -TERM openvpn
. bridge-stop.sh
Проблемы и возможности
Для отключения шифрования траффика и авторизации по сертификату блок tls-client в client.ovpn и блок tls-server в server.ovpn нужно заменить на cipher none.
Здесь приведён простейший случай, когда протоколом является UDP и порт 1194 — стандартный для openvpn. При работе за http-proxy c ntlm-авторизацией могут потребоваться дополнительные действия. В этом случае необходимо знать адрес и порт http-proxy. Настройка auto-proxy у меня не работала (скорее всего из-за ntlm-авторизации). Адрес/порт в худшем случае (когда не опубликован и не видно в настройках браузера) можно узнать из файла wpad.domain/wpad.dat (язык — JavaScript), где domain — имя вашего домена. OpenVPN GUI похоже поддерживает только plain-text тип авторизации basic. Для ntlm же придётся создать файл с логином в первой строке и паролем во второй. В client.ovpn необходимо добавить строки:
http-proxy proxy 8080 "passwd" ntlm
http-proxy-option AGENT Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/535.11+
(KHTML,+like+Gecko)+Chrome/17.0.963.56+Safari/535.11
где passwd — имя файла с логином/паролем к http-proxy, proxy — IP/URL http-proxy, а вторая команда необходима для того, чтобы клиент представил себя браузером прокси-серверу (мне пригождалась в борьбе с админами на работе). Сохранение логина/пароля в файле удобно, когда необходимо, чтобы openvpn стартовал с системой (для доступа по RDP, например, из дому). Для этого его необходимо настроить как стартующую автоматически службу. Кроме того необходимо сменить протокол на TCP и порт на 443:
Клиент:
nobind
proto tcp-client
rport 443
remote X.Y.Z.100
Сервер:
proto tcp-server
lport 443
local X.Y.Z.100
Итог
Цель достигнута. Имеем белый IP дома/на работе не смотря на то, что находимся за http-proxy/NAT.
Источники
Команды/настройки openvpn
openvpn howto
P.S.: Спасибо за консультации Dmitry_Milk в попытках создать proof of concept.
Автор: Dukales