Проксирование трафика с сохранением исходного IP-адреса — задача, которая часто встречается при построении распределённой инфраструктуры. GRE туннели позволяют элегантно решить эту проблему, создавая виртуальный канал между серверами. В отличие от традиционных методов с использованием DNAT, подход с чистой маршрутизацией обеспечивает большую гибкость и производительность.
В этой статье мы рассмотрим настройку GRE туннеля поверх IPv6 для проксирования трафика между VPS и выделенным сервером. Я покажу не только команды, но и объясню логику работы каждого компонента, чтобы вы могли адаптировать решение под свои задачи.
GRE (Generic Routing Encapsulation) — это протокол туннелирования, который позволяет инкапсулировать практически любой сетевой протокол внутри IP-пакетов, создавая виртуальные point-to-point соединения.
1. Архитектура решения
Схема работы
Наша схема состоит из двух серверов:
- VPS (источник) — принимает входящий трафик на PROXY_IP
- Dedicated (назначение) — обрабатывает трафик и возвращает ответы
Трафик проходит следующий путь:
- Клиент подключается к PROXY_IP на VPS
- VPS инкапсулирует пакеты в GRE туннель
- Туннель проходит по IPv6 между серверами
- Dedicated-сервер декапсулирует пакеты и обрабатывает их
- Ответы возвращаются тем же путём
Преимущества подхода
- Сохранение источника трафика — конечный сервер видит реальный IP клиента
- Использование IPv6 — экономия IPv4-адресов и обход некоторых сетевых ограничений
- Чистая маршрутизация — отсутствие NAT упрощает отладку и повышает производительность
- Гибкость — легко масштабируется на несколько серверов
Важно!
GRE туннели не шифруют трафик. Если требуется конфиденциальность, используйте IPsec поверх GRE или альтернативные решения типа WireGuard.
2. Подготовка к настройке
Проверка требований
Перед началом настройки убедитесь в выполнении следующих условий:
- Ядро Linux версии 3.7 или новее (для поддержки ip6_gre)
- Наличие IPv6-адресов на обоих серверах
- Доступность серверов друг для друга по IPv6
- Свободный IPv4-адрес для проксирования
# Проверка версии ядра
uname -r
# Проверка наличия модуля ip6_gre
modprobe ip6_gre && echo "Модуль доступен" || echo "Модуль отсутствует"
# Проверка IPv6 связности
ping6 -c 3 <ipv6-адрес-удалённого-сервера>
# Проверка загруженных туннельных модулей
lsmod | grep gre
Определение переменных окружения
Для удобства работы определим все необходимые параметры как переменные. Это упростит копирование команд и снизит вероятность ошибок.
# Адреса внутри туннеля (частная сеть)
SRC_TNL_IP=10.10.10.1 # IP туннеля на VPS
DST_TNL_IP=10.10.10.2 # IP туннеля на дедике
# IPv4-адрес для проксирования
PROXY_IP=203.0.113.50 # Замените на ваш адрес
# IPv6-адреса серверов (для транспорта туннеля)
SRC_IP6=2001:db8::1 # IPv6 VPS
DST_IP6=2001:db8::2 # IPv6 дедика
Совет
Сохраните эти переменные в файл /root/gre-config.sh для быстрого повторного использования:
export SRC_TNL_IP=10.10.10.1
export DST_TNL_IP=10.10.10.2
export PROXY_IP=203.0.113.50
export SRC_IP6=2001:db8::1
export DST_IP6=2001:db8::2
Загрузите переменные:
source /root/gre-config.sh
3. Настройка VPS (входной точки)
VPS принимает входящий трафик и направляет его через туннель на dedicated-сервер.
Включение IP-форвардинга
Первым делом необходимо разрешить серверу пересылать пакеты между интерфейсами:
# Включение немедленно
sysctl -w net.ipv4.ip_forward=1
# Постоянное включение после перезагрузки
sed -i 's/.*net\.ipv4\.ip_forward.*/net.ipv4.ip_forward=1/' /etc/sysctl.d/99-sysctl.conf
# Если файл не существует, создаём
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.d/99-sysctl.conf
Настройка сетевого интерфейса
Добавьте следующий блок в конец файла /etc/network/interfaces:
auto gre1
iface gre1 inet static
address $SRC_TNL_IP
netmask 255.255.255.0
# Создание туннеля при поднятии интерфейса
pre-up ip -6 tunnel add gre1 mode ip6gre local $SRC_IP6 remote $DST_IP6 ttl 255
post-down ip tunnel del gre1
# Удаление PROXY_IP с физического интерфейса
up ip a del $PROXY_IP/24 dev ens3
# ARP-прокси для перехвата трафика
up arp -sD $PROXY_IP ens3 pub
# Создание таблицы маршрутизации для туннеля
up ip route add default via $DST_TNL_IP dev gre1 table 100
up ip rule add from all to $PROXY_IP/32 lookup 100
# Исправление MSS для предотвращения фрагментации
up iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
# Очистка при выключении интерфейса
post-down arp -d $PROXY_IP dev ens3
post-down ip route del default via $DST_TNL_IP dev gre1 table 100
post-down ip rule del from all to $PROXY_IP/32 lookup 100
post-down iptables -D FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
Понимание конфигурации
Разберём ключевые элементы:
- ip -6 tunnel add — создаёт GRE туннель поверх IPv6
- arp -sD … pub — публикует ARP-запись, перехватывая трафик для PROXY_IP
- table 100 — отдельная таблица маршрутизации для изоляции правил туннеля
- ip rule — политика маршрутизации (policy routing) для направления трафика в туннель
- TCPMSS --clamp-mss-to-pmtu — автоматическая корректировка MSS во избежание фрагментации пакетов
Активация в runtime (без перезагрузки)
Если требуется поднять туннель немедленно:
# Создание туннельного интерфейса
ip -6 tunnel add gre1 mode ip6gre local $SRC_IP6 remote $DST_IP6 ttl 255
# Присвоение IP-адреса
ip addr add $SRC_TNL_IP/24 dev gre1
# Активация интерфейса
ip link set gre1 up
# Удаление PROXY_IP с основного интерфейса (замените ens3 на ваш)
ip addr del $PROXY_IP/24 dev ens3
# Публикация ARP
arp -sD $PROXY_IP ens3 pub
# Настройка маршрутизации
ip route add default via $DST_TNL_IP dev gre1 table 100
ip rule add from all to $PROXY_IP/32 lookup 100
# Исправление MSS
iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
Проверка конфигурации VPS
# Проверка состояния интерфейса
ip addr show gre1
# Проверка таблицы маршрутизации
ip route show table 100
# Проверка правил маршрутизации
ip rule list
# Проверка ARP-записей
arp -n | grep $PROXY_IP
# Проверка правил iptables
iptables -L FORWARD -v -n
4. Настройка Dedicated-сервера (конечной точки)
Включение IP-форвардинга
Аналогично VPS, включаем пересылку пакетов:
# Немедленное включение
sysctl -w net.ipv4.ip_forward=1
# Постоянная настройка
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.d/99-sysctl.conf
# Или раскомментируйте в /etc/sysctl.conf для старых дистрибутивов
Настройка туннельного интерфейса
Добавьте следующий блок в конец файла /etc/network/interfaces:
auto gre1
iface gre1 inet static
address $DST_TNL_IP
netmask 255.255.255.0
# Загрузка модуля ядра
pre-up modprobe ip6_gre
# Создание туннеля (обратите внимание на порядок local/remote)
pre-up ip -6 tunnel add gre1 mode ip6gre local $DST_IP6 remote $SRC_IP6 ttl 255
post-down ip tunnel del gre1
# Добавление PROXY_IP на loopback
up ip addr add $PROXY_IP/32 dev lo
# Маршрутизация ответов через туннель
up ip route add default via $SRC_TNL_IP dev gre1 table 100
up ip rule add from $PROXY_IP/32 lookup 100
# Исправление MSS
up iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
# Очистка при выключении
post-down ip addr del $PROXY_IP/32 dev lo
post-down ip route del default via $SRC_TNL_IP dev gre1 table 100
post-down ip rule del from $PROXY_IP/32 lookup 100
post-down iptables -D FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
Активация в runtime
# Создание туннеля (обратите внимание: local и remote поменялись местами)
ip -6 tunnel add gre1 mode ip6gre local $DST_IP6 remote $SRC_IP6 ttl 255
# Присвоение IP
ip addr add $DST_TNL_IP/24 dev gre1
# Активация
ip link set gre1 up
# Добавление PROXY_IP на loopback для приёма трафика
ip addr add $PROXY_IP/32 dev lo
# Маршрутизация исходящего трафика от PROXY_IP через туннель
ip route add default via $SRC_TNL_IP dev gre1 table 100
ip rule add from $PROXY_IP/32 lookup 100
# Исправление MSS
iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
Проверка конфигурации Dedicated
# Состояние туннеля
ip addr show gre1
ip link show gre1
# Проверка PROXY_IP на loopback
ip addr show lo | grep $PROXY_IP
# Таблица маршрутизации
ip route show table 100
# Правила маршрутизации
ip rule list | grep -E "100|$PROXY_IP"
# Тестирование связности через туннель
ping -c 3 $SRC_TNL_IP
5. Тестирование и отладка
Проверка связности туннеля
С VPS:
# Ping через туннель
ping -c 5 $DST_TNL_IP
# Трассировка маршрута
traceroute $DST_TNL_IP
# Проверка MTU
ping -c 1 -M do -s 1400 $DST_TNL_IP
С Dedicated:
# Ping обратно
ping -c 5 $SRC_TNL_IP
# Проверка доступности PROXY_IP локально
ping -c 3 $PROXY_IP -I $PROXY_IP
Тестирование проксирования
С внешнего клиента:
# HTTP-запрос (если на dedicated запущен веб-сервер)
curl -v http://$PROXY_IP
# Проверка исходного IP в логах сервера
# На dedicated проверьте логи, должен отображаться реальный IP клиента
tail -f /var/log/nginx/access.log
# или
tail -f /var/log/apache2/access.log
Мониторинг трафика в туннеле
# Захват трафика на туннельном интерфейсе
tcpdump -i gre1 -n
# Подробный просмотр с дешифровкой
tcpdump -i gre1 -vvv -n
# Сохранение в файл для анализа в Wireshark
tcpdump -i gre1 -w /tmp/gre-capture.pcap
# Просмотр статистики интерфейса
ip -s link show gre1
# Мониторинг в реальном времени
watch -n 1 'ip -s link show gre1'
Проверка таблиц маршрутизации
# Все таблицы маршрутизации
ip route show table all | grep gre1
# Конкретная таблица
ip route show table 100
# Проверка какой маршрут будет выбран для пакета
ip route get $PROXY_IP
# Из какого источника
ip route get $PROXY_IP from 8.8.8.8
6. Устранение типичных проблем
Проблема: туннель не поднимается
Симптомы: интерфейс gre1 отсутствует или в состоянии DOWN
Решение:
# Проверка загрузки модуля
lsmod | grep ip6_gre
# Принудительная загрузка
modprobe ip6_gre
# Проверка доступности IPv6
ping6 -c 3 $DST_IP6 # (или $SRC_IP6 с другого конца)
# Проверка журнала ядра на ошибки
dmesg | grep -i gre
journalctl -k | grep -i tunnel
Проблема: трафик не проходит через туннель
Симптомы: ping работает, но HTTP/другой трафик не проходит
Решение:
# Проверка, активна ли пересылка пакетов
sysctl net.ipv4.ip_forward
# Проверка firewall правил
iptables -L -v -n
iptables -L FORWARD -v -n
# Временное отключение firewall для теста
iptables -P FORWARD ACCEPT
# Проверка policy routing
ip rule list
ip route show table 100
# Трассировка пакетов
traceroute -n $PROXY_IP
Проблема: медленная скорость или потеря пакетов
Симптомы: высокий ping, потери пакетов, низкая пропускная способность
Причина: фрагментация пакетов из-за overhead GRE туннеля
Решение:
# Убедитесь, что правило TCPMSS добавлено
iptables -L FORWARD -v -n | grep TCPMSS
# Если отсутствует, добавьте
iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
# Проверка MTU на интерфейсах
ip link show gre1
# Ручная установка MTU (обычно 1476 для GRE over IPv6)
ip link set gre1 mtu 1476
# Тестирование разных размеров пакетов
ping -c 5 -M do -s 1400 $DST_TNL_IP
ping -c 5 -M do -s 1450 $DST_TNL_IP
Проблема: ARP не работает на VPS
Симптомы: трафик не приходит на VPS для PROXY_IP
Решение:
# Проверка ARP-записи
arp -n | grep $PROXY_IP
# Удаление и повторное добавление
arp -d $PROXY_IP dev ens3
arp -sD $PROXY_IP ens3 pub
# Проверка, что IP удалён с физического интерфейса
ip addr show ens3 | grep $PROXY_IP
# Если присутствует, удалите
ip addr del $PROXY_IP/24 dev ens3
# Отправка тестового ARP-запроса
arping -I ens3 $PROXY_IP
Проблема: dedicated не отвечает на трафик
Симптомы: трафик приходит на dedicated, но ответы не возвращаются
Решение:
# Проверка, что PROXY_IP добавлен на loopback
ip addr show lo | grep $PROXY_IP
# Проверка правила маршрутизации источника
ip rule list | grep $PROXY_IP
# Проверка маршрута для исходящего трафика
ip route get 8.8.8.8 from $PROXY_IP
# Должен показывать маршрут через gre1
# Проверка, принимает ли приложение соединения на PROXY_IP
ss -tlnp | grep $PROXY_IP
netstat -tlnp | grep $PROXY_IP
# Настройка приложения для прослушивания на всех интерфейсах
# Например, для Nginx в /etc/nginx/sites-available/default:
# listen 80 default_server;
# вместо
# listen 127.0.0.1:80;
7. Оптимизация и best practices
Постоянство конфигурации
Убедитесь, что все настройки сохранятся после перезагрузки:
# Проверка конфигурации в /etc/network/interfaces
cat /etc/network/interfaces | grep -A 20 "auto gre1"
# Проверка sysctl настроек
cat /etc/sysctl.d/99-sysctl.conf | grep ip_forward
# Сохранение правил iptables (для Debian/Ubuntu)
apt install iptables-persistent
iptables-save > /etc/iptables/rules.v4
# Для CentOS/RHEL
service iptables save
Мониторинг состояния туннеля
Создайте файл /usr/local/bin/check-gre-tunnel.sh со следующим содержимым:
#!/bin/bash
REMOTE_IP="10.10.10.2" # Удалённый конец туннеля
if ! ip link show gre1 &>/dev/null; then
echo "ERROR: Interface gre1 does not exist"
exit 1
fi
if ! ip link show gre1 | grep -q "state UP"; then
echo "ERROR: Interface gre1 is DOWN"
exit 1
fi
if ! ping -c 1 -W 2 $REMOTE_IP &>/dev/null; then
echo "ERROR: Cannot reach remote end of tunnel"
exit 1
fi
echo "OK: GRE tunnel is operational"
exit 0
Сделайте скрипт исполняемым и добавьте в cron для регулярной проверки:
chmod +x /usr/local/bin/check-gre-tunnel.sh
# Проверка каждые 5 минут с автоматическим перезапуском туннеля при сбое
echo "*/5 * * * * /usr/local/bin/check-gre-tunnel.sh || /sbin/ifdown gre1 && /sbin/ifup gre1" | crontab -
Логирование проблем
# Логирование отброшенных пакетов в FORWARD цепочке
iptables -I FORWARD -j LOG --log-prefix "GRE-FORWARD: " --log-level 4
# Просмотр логов
tail -f /var/log/kern.log | grep GRE-FORWARD
# Удаление правила после отладки
iptables -D FORWARD -j LOG --log-prefix "GRE-FORWARD: " --log-level 4
Безопасность
# Ограничение доступа к туннелю по IPv6
ip6tables -A INPUT -s $DST_IP6 -p ipv6-icmp -j ACCEPT # VPS
ip6tables -A INPUT -s $SRC_IP6 -p ipv6-icmp -j ACCEPT # Dedicated
ip6tables -A INPUT -s $DST_IP6 -p 47 -j ACCEPT # VPS, протокол GRE
ip6tables -A INPUT -s $SRC_IP6 -p 47 -j ACCEPT # Dedicated
# Блокировка остального трафика (опционально)
ip6tables -P INPUT DROP
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Документирование конфигурации
Создайте файл /root/gre-tunnel-info.txt с описанием настройки:
GRE Tunnel Configuration
========================
Date configured: <текущая дата>
VPS IPv6: $SRC_IP6
Dedicated IPv6: $DST_IP6
Tunnel network: $SRC_TNL_IP - $DST_TNL_IP
Proxied IP: $PROXY_IP
Routing table ID: 100
To restart tunnel:
ifdown gre1 && ifup gre1
To check status:
/usr/local/bin/check-gre-tunnel.sh
To view traffic:
tcpdump -i gre1 -n
8. Заключение
GRE туннели — мощный инструмент для построения сетевой инфраструктуры. Представленная конфигурация с использованием чистой маршрутизации обеспечивает:
- Прозрачность — приложения видят реальные IP-адреса клиентов
- Гибкость — легко добавить дополнительные туннели и IP-адреса
- Производительность — минимальный overhead по сравнению с NAT
- Простоту отладки — всё работает на уровне маршрутизации
Помните о ключевых моментах:
- GRE не обеспечивает шифрование — используйте IPsec при необходимости
- Правильная настройка MSS критична для производительности
- Policy routing (ip rule) позволяет гибко управлять трафиком
- Мониторинг состояния туннеля предотвращает простои
Успешной настройки! При возникновении проблем обращайтесь к разделу отладки и не забывайте проверять логи системы.