Белый интерфейс за NAT/proxy

в 20:57, , рубрики: bridge, openvpn, tap, vpn, Песочница, метки: , , ,

В статье рассказывается о том, что необходимо сделать, чтобы иметь на локальной машине интерфейс с белым 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


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js