Как я могу форсировать весь интернет-трафик через PPTP VPN, но все же разрешить локальный доступ к локальной сети?
У меня есть сервер под управлением Linux Mint 12, который я хочу постоянно подключать к PPTP VPN. VPN-сервер довольно надежен, но иногда он падает, поэтому я просто хочу сделать так, чтобы вся интернет-активность была отключена, если VPN-соединение разорвано.
Я также хотел бы найти способ перезапустить его автоматически, но это не такая большая проблема, так как это происходит довольно редко.
Я также хочу всегда иметь возможность подключаться к коробке из моей локальной сети, независимо от того, работает ли VPN или нет.
Вот как выглядит мой ifconfig с подключенным VPN:
eth0 Link encap:Ethernet HWaddr 00:22:15:21:59:9a
inet addr:192.168.0.171 Bcast:192.168.0.255 Mask:255.255.255.0
inet6 addr: fe80::222:15ff:fe21:599a/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:37389 errors:0 dropped:0 overruns:0 frame:0
TX packets:29028 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:37781384 (37.7 MB) TX bytes:19281394 (19.2 MB)
Interrupt:41 Base address:0x8000
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:1446 errors:0 dropped:0 overruns:0 frame:0
TX packets:1446 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:472178 (472.1 KB) TX bytes:472178 (472.1 KB)
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.10.11.10 P-t-P:10.10.11.9 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:14 errors:0 dropped:0 overruns:0 frame:0
TX packets:23 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:1368 (1.3 KB) TX bytes:1812 (1.8 KB)
Вот скрипт iptables, который я нашел в другом месте и который, кажется, предназначен для решения проблемы, которую я пытаюсь решить, но он блокирует весь доступ, но я не уверен, что мне нужно изменить:
#!/bin/bash
#Set variables
IPT=/sbin/iptables
VPN=`ifconfig|perl -nE'/dr:(\S+)/&&say$1'|grep 10.`
LAN=192.168.0.0/24
#Flush rules
$IPT -F
$IPT -X
#Default policies and define chains
$IPT -P OUTPUT DROP
$IPT -P INPUT DROP
$IPT -P FORWARD DROP
#Allow input from LAN and tun0 ONLY
$IPT -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A INPUT -i tun0 -m conntrack --ctstate NEW -j ACCEPT
$IPT -A INPUT -s $LAN -m conntrack --ctstate NEW -j ACCEPT
$IPT -A INPUT -j DROP
#Allow output from lo and tun0 ONLY
$IPT -A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
$IPT -A OUTPUT -o tun0 -m conntrack --ctstate NEW -j ACCEPT
$IPT -A OUTPUT -d $VPN -m conntrack --ctstate NEW -j ACCEPT
$IPT -A OUTPUT -j DROP
exit 0
Спасибо за вашу помощь.
4 ответа
Эти правила iptables не разрешают трафик на сервер VPN, поэтому VPN не может быть установлен. Вам нужны следующие правила в OUTPUT
цепочка перед финалом DROP
Правило, где 1.2.3.4 - IP-адрес VPN-сервера. Это позволяет устанавливать TCP-соединения с портом 1723 (канал управления PPTP) и пакетами GRE (канал данных).
iptables --append OUTPUT --destination 1.2.3.4 --protocol tcp --dport 1723 --jump ACCEPT
iptables --append OUTPUT --destination 1.2.3.4 --protocol gre --jump ACCEPT
Есть два подхода к этому: на основе маршрутизации и на основе брандмауэра.
Маршрутный подход
Типичная таблица маршрутизации машины, не подключенной к VPN, выглядит примерно так:
10.23.11.0/24 dev eth0
default via 10.23.11.1
Первый маршрут предназначен для хостов в локальной сети, а второй маршрут отправляет все остальное на шлюз по умолчанию. При подключении к VPN таблица маршрутизации выглядит примерно так (где 1.2.3.4 - публичный IP-адрес VPN-сервера, а 10.8.0.1 - частный IP-адрес VPN-сервера):
10.23.11.0/24 dev eth0
1.2.3.4 via 10.23.11.1
default via 10.8.0.1
Первый маршрут такой же, а третий - это то, что отправляет все через VPN. Однако обратите внимание на второе правило: оно говорит, что для достижения публичного IP-сервера VPN-сервера пакеты должны отправляться через шлюз по умолчанию. Это так, что туннелированные пакеты, созданные VPN-клиентом, фактически достигают сервера; если этот маршрут отсутствует, пакеты, созданные VPN-клиентом, будут снова отправляться через VPN и никогда не попадут на сервер.
Теперь, если третий маршрут будет удален, то пакеты, предназначенные для любого места в Интернете, кроме VPN-сервера, не будут иметь соответствующий маршрут, и поэтому хост никогда не будет отправлять их. Поэтому мы хотим, чтобы таблица маршрутизации выглядела так, когда VPN не подключена:
10.23.11.0/24 dev eth0
1.2.3.4 via 10.23.11.1
Хосты в локальной сети все еще могут быть доступны, и VPN-сервер все еще может быть достигнут (поскольку мы должны иметь возможность запустить VPN), но все остальное не будет маршрутизировано. Получить эту настройку может быть немного сложно, особенно если вы используете DHCP. Статическая конфигурация в Debian будет включать в себя следующее /etc/network/interfaces
тем не мение:
auto eth0
iface eth0 inet static
address 10.23.11.10
netmask 255.255.255.0
up ip route add 1.2.3.4 via 10.23.11.1
Обратите внимание, что нет gateway
заявление, так как это то, что устанавливает маршрут по умолчанию.
Недостатком этого подхода является то, что не VPN-трафик на VPN-сервер по-прежнему разрешен в незашифрованном виде. Если вы запускаете другие службы на VPN-сервере и вам необходимо обеспечить их защиту, вам придется использовать подход брандмауэра.
Изменить: @JamesRyan предполагает, что этот подход является хрупким, потому что маршрут по умолчанию может быть добавлен автоматически или случайно. Другой подход состоит в том, чтобы добавить маршрут черной дыры, который отправляет трафик куда-то, что не будет направлять его дальше. Однако это не будет работать с автоматически добавленным маршрутом по умолчанию, поскольку он уже использует метрику с наивысшим приоритетом 0. Маршрут по умолчанию все еще необходимо удалить, но затем можно добавить что-то вроде следующего.
default via 127.255.255.255
Брандмауэр подход
Идея заключается в том, чтобы блокировать весь исходящий трафик на физическом интерфейсе, кроме туннелированного трафика, создаваемого VPN-клиентом, и трафика, предназначенного для локальной сети. Трафик для разрешения VPN зависит от используемого протокола. PPTP использует TCP-порт 1723 в качестве канала управления и GRE в качестве фактического туннеля. OpenVPN использует UDP-порт 1194. Правила брандмауэра будут выглядеть примерно так:
iptables --append OUTPUT --out-interface eth0 --destination 10.23.11.0/24 --jump ACCEPT
iptables --append OUTPUT --out-interface eth0 --destination 1.2.3.4 --protocol tcp --dport 1723 --jump ACCEPT
iptables --append OUTPUT --out-interface eth0 --destination 1.2.3.4 --protocol gre --jump ACCEPT
iptables --append OUTPUT --out-interface eth0 --jump REJECT
Первое правило принимает трафик для локальной сети. Второе и третье правила принимают VPN-трафик к VPN-серверу. Четвертое правило отклоняет весь другой трафик, выходящий из физического интерфейса.
Еще одна вещь, которую вам может потребоваться принять - это DNS, если вы используете DNS-сервер, который не находится в локальной сети, поскольку VPN-клиенту, вероятно, необходимо выполнить поиск DNS, чтобы найти VPN-сервер. Следующее правило вставлено перед REJECT
позволит DNS-трафик на общедоступную службу DNS Google.
iptables --append OUTPUT --out-interface eth0 --destination 8.8.8.8 --protocol udp --dport 53 --jump ACCEPT
Добавьте другой маршрут по умолчанию с более высокой метрикой, указывающей на нулевой интерфейс. Когда VPN недоступен, 2-й маршрут активирует трафик
Это не квестон iptables - для этого вам не нужен iptables.
Просто установите маршрут по умолчанию, чтобы пройти через VPN, и все готово. Вы также можете добавить другой маршрут по умолчанию с худшим показателем для использования, когда VPN не работает.
Ваша локальная сеть подключена напрямую, поэтому она имеет приоритет над шлюзом по умолчанию.