Нужно направить интернет-трафик ноутбука через собственный VPS. Для этого недостаточно запустить OpenVPN: сервер должен выдавать клиенту адрес, принимать его пакеты, пересылать их в интернет и подменять исходный адрес с помощью NAT.
В результате мы получим один файл macbook-internet.ovpn. Его можно импортировать в Tunnelblick или OpenVPN Connect на macOS.
Гайд рассчитан на Ubuntu 22.04 или 24.04 и OpenVPN Community Edition. Основная конфигурация направляет через VPN весь IPv4-трафик. Настройка двух одновременных VPN вынесена в отдельный раздел в конце.
Что потребуется
- VPS с Ubuntu и доступом по SSH;
- публичный IPv4-адрес или проброс UDP-порта через NAT провайдера;
- открытый входящий порт
1194/UDP; - клиент Tunnelblick или OpenVPN Connect.
В примерах используются:
Публичный адрес VPS: 203.0.113.10
VPN-подсеть: 10.90.0.0/24
VPN-сервер: 10.90.0.1
Первый клиент: macbook
Адрес 203.0.113.10 зарезервирован для документации. Замените его на публичный адрес своего VPS.
VPN-подсеть не должна совпадать с сетью VPS, домашней сетью или другими VPN. Например, если интерфейс VPS находится в 192.168.0.0/24, оставьте для OpenVPN отдельную сеть 10.90.0.0/24.
Установка OpenVPN
Установим OpenVPN, Easy-RSA для выпуска сертификатов и UFW для настройки сетевого экрана:
sudo apt update
sudo apt install -y openvpn easy-rsa ufw
Ubuntu рекомендует пакеты openvpn и easy-rsa в официальной инструкции.
Создание сертификатов
Создадим каталог Easy-RSA и перейдём в root-сессию:
sudo make-cadir /etc/openvpn/easy-rsa
sudo -i
cd /etc/openvpn/easy-rsa
Создадим инфраструктуру открытых ключей (Public Key Infrastructure, PKI):
./easyrsa init-pki
./easyrsa build-ca
Команда build-ca попросит задать пароль центра сертификации и его имя. Пароль понадобится при выпуске и отзыве клиентских сертификатов.
Создадим ключ и сертификат сервера:
./easyrsa gen-req vpn-server nopass
./easyrsa sign-req server vpn-server
При подписании введите yes, затем пароль центра сертификации.
Создадим сертификат первого клиента:
./easyrsa gen-req macbook nopass
./easyrsa sign-req client macbook
Параметр nopass позволяет подключаться без ввода пароля от клиентского ключа. После этого файл .ovpn нужно хранить как секрет: любой, кто получит его копию, сможет подключиться к серверу.
Создадим список отозванных сертификатов:
./easyrsa gen-crl
Установка ключей сервера
Создадим каталог конфигурации и скопируем в него только серверные файлы:
install -d -m 700 /etc/openvpn/server
install -m 644 pki/ca.crt /etc/openvpn/server/ca.crt
install -m 644 pki/issued/vpn-server.crt /etc/openvpn/server/vpn-server.crt
install -m 600 pki/private/vpn-server.key /etc/openvpn/server/vpn-server.key
install -m 644 pki/crl.pem /etc/openvpn/server/crl.pem
Создадим ключ tls-crypt:
openvpn --genkey tls-crypt /etc/openvpn/server/tls-crypt.key
chmod 600 /etc/openvpn/server/tls-crypt.key
tls-crypt шифрует и проверяет управляющий канал OpenVPN. В отличие от tls-auth, он не требует параметра key-direction.
Конфигурация OpenVPN
Создайте файл /etc/openvpn/server/internet.conf:
nano /etc/openvpn/server/internet.conf
Добавьте конфигурацию:
port 1194
proto udp4
dev tun-inet
topology subnet
server 10.90.0.0 255.255.255.0
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/vpn-server.crt
key /etc/openvpn/server/vpn-server.key
crl-verify /etc/openvpn/server/crl.pem
dh none
tls-crypt /etc/openvpn/server/tls-crypt.key
tls-version-min 1.2
remote-cert-tls client
data-ciphers AES-256-GCM:AES-128-GCM
push "redirect-gateway def1"
push "dhcp-option DNS 213.148.0.221"
push "dhcp-option DNS 213.148.0.222"
keepalive 10 120
persist-key
persist-tun
user nobody
group nogroup
explicit-exit-notify 1
verb 3
В примере используются DNS-серверы 213.148.0.221 и 213.148.0.222. Если провайдер выдал другие адреса, замените обе строки dhcp-option DNS.
redirect-gateway def1 создаёт на клиенте маршруты 0.0.0.0/1 и 128.0.0.0/1. Вместе они направляют весь IPv4-трафик через VPN, но сохраняют исходный маршрут по умолчанию. data-ciphers включает современные шифры AES-GCM вместо устаревшей директивы cipher. Эти параметры описаны в руководстве OpenVPN 2.6.
Включение маршрутизации
Linux по умолчанию не пересылает IPv4-пакеты между интерфейсами. Включим пересылку пакетов, или IP forwarding:
echo 'net.ipv4.ip_forward = 1' > /etc/sysctl.d/70-openvpn-routing.conf
sysctl -p /etc/sysctl.d/70-openvpn-routing.conf
Проверим значение:
sysctl net.ipv4.ip_forward
Ожидаемый результат:
net.ipv4.ip_forward = 1
Настройка NAT и UFW
Сначала определим внешний интерфейс VPS:
ip -4 route show default
Пример результата:
default via 192.168.0.1 dev eth0
В этом случае внешний интерфейс называется eth0. На другом VPS он может называться ens3, ens5 или иначе.
До включения UFW разрешите SSH и OpenVPN:
ufw allow OpenSSH
ufw allow 1194/udp
Если SSH использует нестандартный порт, разрешите его вместо профиля OpenSSH.
Добавьте правило пересылки пакетов из VPN во внешний интерфейс. Замените eth0 на имя своего интерфейса:
ufw route allow in on tun-inet out on eth0 from 10.90.0.0/24
Теперь откройте /etc/ufw/before.rules:
nano /etc/ufw/before.rules
В начало файла, перед существующей секцией *filter, добавьте:
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.90.0.0/24 -o eth0 -j MASQUERADE
COMMIT
Здесь также замените eth0 на внешний интерфейс VPS.
Правило MASQUERADE меняет адрес клиента 10.90.0.x на адрес сервера. Благодаря этому ответы из интернета возвращаются на VPS, а затем попадают в VPN-туннель. Подробно эта схема разобрана в документации Ubuntu по IP masquerading.
Включите firewall:
ufw enable
ufw reload
ufw status verbose
Не закрывайте текущую SSH-сессию, пока не убедитесь, что правило SSH присутствует в выводе ufw status.
Запуск сервера
Запустим OpenVPN и добавим его в автозагрузку:
systemctl enable --now openvpn-server@internet
Проверим службу, порт и туннельный интерфейс:
systemctl status openvpn-server@internet
ss -lunp | grep 1194
ip address show tun-inet
У интерфейса tun-inet должен быть адрес 10.90.0.1/24.
Если служба не запустилась, выведите журнал:
journalctl -u openvpn-server@internet -n 100 --no-pager
VPS за NAT провайдера
Иногда VPS получает частный адрес, а провайдер связывает его с публичным:
Интернет -> 203.0.113.10 -> 192.168.0.2 -> VPS
В такой схеме:
- в клиентском профиле указывают публичный адрес
203.0.113.10; - NAT OpenVPN использует реальный интерфейс VPS с адресом
192.168.0.2; - в конфигурацию сервера не добавляют
local 203.0.113.10; - провайдер должен направлять
1194/UDPс публичного адреса на VPS.
Если провайдер использует полный 1:1 NAT, проброс обычно работает автоматически. При наличии отдельного firewall или security group разрешите в нём 1194/UDP.
Создание клиентского профиля
Мы уже находимся в root-сессии. Зададим публичный адрес сервера и имя клиента:
PUBLIC_IP="203.0.113.10"
CLIENT="macbook"
OUT="/root/${CLIENT}-internet.ovpn"
Замените 203.0.113.10 на адрес своего VPS.
Создадим основную часть профиля:
cat > "$OUT" <<EOF
client
dev tun
proto udp4
remote ${PUBLIC_IP} 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
verify-x509-name vpn-server name
data-ciphers AES-256-GCM:AES-128-GCM
explicit-exit-notify 1
verb 3
<ca>
EOF
Добавим сертификаты и ключи:
sed -ne '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' \
/etc/openvpn/easy-rsa/pki/ca.crt >> "$OUT"
echo '</ca>' >> "$OUT"
echo '<cert>' >> "$OUT"
sed -ne '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' \
"/etc/openvpn/easy-rsa/pki/issued/${CLIENT}.crt" >> "$OUT"
echo '</cert>' >> "$OUT"
echo '<key>' >> "$OUT"
cat "/etc/openvpn/easy-rsa/pki/private/${CLIENT}.key" >> "$OUT"
echo '</key>' >> "$OUT"
echo '<tls-crypt>' >> "$OUT"
cat /etc/openvpn/server/tls-crypt.key >> "$OUT"
echo '</tls-crypt>' >> "$OUT"
chmod 600 "$OUT"
Получился автономный профиль /root/macbook-internet.ovpn.
Если для SSH используется пользователь ubuntu, скопируйте профиль в его домашний каталог:
install -o ubuntu -g ubuntu -m 600 \
/root/macbook-internet.ovpn \
/home/ubuntu/macbook-internet.ovpn
exit
На Mac загрузите файл:
scp ubuntu@203.0.113.10:macbook-internet.ovpn ~/Downloads/
Замените имя пользователя и адрес VPS. После импорта удалите временную копию из домашнего каталога на сервере:
ssh ubuntu@203.0.113.10 'rm ~/macbook-internet.ovpn'
Профиль содержит незашифрованный клиентский ключ. После проверки удалите /root/macbook-internet.ovpn с VPS или перенесите его в зашифрованное резервное хранилище.
Настройка клиента на macOS
Импортируйте macbook-internet.ovpn в Tunnelblick или OpenVPN Connect.
Для Tunnelblick:
- Выберите профиль в
VPN Details. - Оставьте включённой настройку
Set nameserver. - Включите
Disable IPv6, чтобы IPv6-трафик не обходил VPN. - Подключите профиль.
Tunnelblick по умолчанию отключает IPv6 для TUN-подключений, но настройку стоит проверить. Это поведение описано в документации Tunnelblick.
Для OpenVPN Connect:
- Импортируйте профиль из файла.
- В настройках включите
Block IPv6. - Включите
Seamless Tunnel, если нужно блокировать интернет во время переподключения VPN. - Подключите профиль.
OpenVPN Connect описывает параметры Block IPv6 и Seamless Tunnel в настройках клиента для macOS.
Проверка
Сначала узнайте текущий публичный IPv4 без VPN:
curl -4 https://api.ipify.org
echo
Подключите VPN и повторите команду. Теперь она должна показать публичный адрес VPS.
Проверьте маршрут:
route -n get 1.1.1.1
В поле interface должен быть указан интерфейс utun.
Проверьте DNS:
scutil --dns
В списке должны появиться DNS-серверы, заданные в internet.conf.
Проверьте IPv6:
curl -6 --connect-timeout 5 https://api64.ipify.org
Если сервер не настроен для маршрутизации IPv6, команда должна завершиться ошибкой. Публичный IPv6 домашнего провайдера означает, что трафик обходит туннель.
На сервере можно проверить передачу пакетов:
ip -s link show tun-inet
Счётчики RX и TX должны увеличиваться при работе клиента.
Если VPN подключился, но интернета нет
Проверьте четыре места:
sysctl net.ipv4.ip_forward
sudo ufw status verbose
sudo iptables -t nat -S POSTROUTING
sudo journalctl -u openvpn-server@internet -n 100 --no-pager
Типичные причины:
net.ipv4.ip_forwardравен0;- в правиле
MASQUERADEуказано неправильное имя интерфейса; - провайдер не пропускает
1194/UDP; - UFW разрешает подключение к OpenVPN, но запрещает forwarding;
- VPN-подсеть пересекается с локальной сетью клиента.
Опция: два VPN одновременно
Допустим, первый VPN даёт доступ только к сети 10.128.66.0/24, а второй VPN из этого гайда должен обслуживать остальной интернет.
OpenVPN Connect на macOS не поддерживает два одновременных подключения. Для такой схемы используйте Tunnelblick: он умеет держать несколько туннелей, хотя предупреждает о конфликтах маршрутов и DNS. Ограничение OpenVPN Connect указано в его официальном FAQ.
Маршрут первого VPN
Первый профиль должен получать только маршрут к нужной сети:
route 10.128.66.0 255.255.255.0
Если этот маршрут уже присылает первый сервер, добавлять его в профиль не нужно.
Чтобы управляющее соединение первого VPN не попало во второй туннель, добавьте маршрут к адресу первого сервера в оба профиля:
route 198.51.100.20 255.255.255.255 net_gateway
Замените 198.51.100.20 на адрес первого VPN-сервера. net_gateway означает обычный шлюз, который существовал до подключения VPN.
DNS
Только один профиль Tunnelblick должен менять системный DNS:
- первый VPN для
10.128.66.0/24-Do not set nameserver; - второй интернет-VPN -
Set nameserver.
Перед подключением Tunnelblick должен показывать одно соединение с установкой DNS-сервера и одно без неё. Подключайте первый VPN раньше интернет-VPN, а отключайте в обратном порядке. Это снижает риск неправильного восстановления DNS, но Tunnelblick всё равно предупреждает, что автоматическое переподключение одного из туннелей может нарушить порядок настроек.
Если корпоративные ресурсы открываются по внутренним DNS-именам, потребуется отдельная настройка split DNS. Доступ по IP-адресам от этого не зависит.
Порядок подключения
- Подключите первый VPN.
- Проверьте доступ к
10.128.66.0/24. - Подключите интернет-VPN.
Проверьте маршруты:
route -n get 10.128.66.1
route -n get 198.51.100.20
route -n get 1.1.1.1
Маршрут к 10.128.66.0/24 должен вести в первый utun. Маршрут к серверу первого VPN должен вести через физический интерфейс en0 или en1. Остальной трафик должен идти во второй utun.
Схема работает по правилу самого длинного префикса. Маршрут 10.128.66.0/24 точнее маршрутов 0.0.0.0/1 и 128.0.0.0/1, поэтому трафик корпоративной сети выбирает первый VPN, а остальной IPv4-трафик - второй.
Итог
Рабочий OpenVPN-сервер состоит из четырёх частей:
- сертификатов сервера и клиента;
- TUN-подсети, которая не пересекается с другими сетями;
- включённой пересылки IPv4 и правила
MASQUERADE; - клиентского профиля с маршрутом по умолчанию и DNS.
Если эти части настроены отдельно и проверены по порядку, искать ошибку обычно приходится в одном конкретном месте, а не во всей сети сразу.
Комментарии в Telegram-группе!