Сам собі тунельний брокер або нативний IPv6 на компі за допомогою OpenVPN

Я — великий прихильник використання IPv6, намагаюся його використовувати, де це тільки можливо. Нещодавно подумавши я вирішив, що на більшості своїх виртуалок переведу ssh на ipv6-only, биндить буду на рандомно вибраний при конфігурації адресу, який потім пропишу в ДНСах для своєї зручності. Але виникло питання з доступом з мого ноутбука до тих кого таким чином настрою. Зрозуміло, що завжди можна ходити через сервер, де у мене IPv6, звичайно ж є, зазвичай я так і роблю, але випадки бувають різні.

Почухавши трохи голову я зрозумів, що я ж можу взяти яку-небудь /112 /64 даваемой хостером і роздати по OpenVPN свого ноута та іншим особистим машин, тим самим отримавши справжній ipv6, а не адресу від брокерів.

Вирішив, значить треба робити. Вибрав для цього віртуалку від vultr, на якій у мене нічого спочатку не було і яка призначена була для тестів і взявся за налагодження.
<habracut/>
Vultr видає виртуалкам мережі /64, у нашому прикладі нехай це буде мережа 2001:NNNN:NNNN:NNNN::/64, з неї ми візьмемо «маленький» шматочок /112, який і будемо роздавати своїм компам, нехай це буде 2001:NNNN:NNNN:NNNN:80::/112. Процедуру генерації ключів для OpenVPN я описувати не буду, вона досить детально описана в інших посібниках, розгляну тільки конфіг і скрипти, які будуть використовуватися для наших цілей.

У файлі /etc/openvpn/variables ми пропишемо мережу і маску які будемо використовувати, звідси у нас це справа заберуть скрипти:

# Subnet
prefix=2001:NNNN:NNNN:NNNN:80::
# netmask
prefixlen=112

Конфіг openvpn-сервера:

# Listen port
port 8149

# Protocol
proto udp

# IP tunnel
dev tap0

# Master certificate
ca ca.crt

# Server certificate
cert server.crt

# Server private key
key server.key

# Diffie-Hellman parameters
dh dh2048.pem

# Allow clients to communicate with each other
client-to-client

# Client config dir
client-config-dir /etc/openvpn/ccd

# Run client-specific script on connection and disconnection
script-security 2
client-connect "/usr/bin/sudo -u root /etc/openvpn/server-clientconnect.sh"
client-disconnect "/usr/bin/sudo -u root /etc/openvpn/server-clientdisconnect.sh"

# Server mode and client subnets
server 10.18.0.0 255.255.255.0
server-ipv6 2001:NNNN:NNNN:NNNN:80::/112
topology subnet

# IPv6 routes
push "route-ipv6 2001:NNNN:NNNN:NNNN::/64"
push "route-ipv6 2000::/3"

persist-key
persist-tun 
# Ping every 10s. Timeout of 120s.
keepalive 10 120

# Enable compression
comp-lzo

# User and group
user vpn
group vpn

# Log a short status
status openvpn-status.log
verb 4 
sndbuf 0
rcvbuf 0

В конфіги у нас прописані скрипти, які будуть запускатися при підключенні і відключенні клієнта:

server-clientconnect.sh
#!/bin/sh

# Check client variables
if [ -z "$ifconfig_pool_remote_ip" ] || [ -z "$common_name" ]; then
echo "Missing environment variable."
exit 1
fi

# Load server variables
. /etc/openvpn/variables

ipv6=""

# Find out if there is a specific config with fixed IPv6 for this client
if [ -f "./etc/openvpn/ccd/$common_name" ]; then
# Get fixed IPv6 from client config file 
ipv6=$(sed -nr 's/^.*ifconfig-ipv6-push[ \t]+([0-9a-fA-F\\:]+).*$/\1/p' "./etc/openvpn/ccd/$common_name")
fi

# Get IPv6 from IPv4
if [ -z "$ipv6" ]; then
ipp=$(echo "$ifconfig_pool_remote_ip" | cut -d. -f4)
if ! [ "$ipp" -ge 2 -a "$ipp" -le 254 ] 2>/dev/null; then
echo "Invalid IPv4 part."
exit 1
fi
hexipp=$(printf '%x' $ipp)
ipv6="$prefix$hexipp"
fi

# Create proxy rule
/sbin/ip -6 neigh add proxy $ipv6 dev eth0

і server-clientdisconnect.sh

#!/bin/sh

# Check client variables
if [ -z "$ifconfig_pool_remote_ip" ] || [ -z "$common_name" ]; then
echo "Missing environment variable."
exit 1
fi

# Load server variables
. /etc/openvpn/variables

ipv6=""

# Find out if there is a specific config with fixed IPv6 for this client
if [ -f "./etc/openvpn/ccd/$common_name" ]; then
# Get fixed IPv6 from client config file 
ipv6=$(sed -nr 's/^.*ifconfig-ipv6-push[ \t]+([0-9a-fA-F\\:]+).*$/\1/p' "./etc/openvpn/ccd/$common_name")
fi

# Get IPv6 from IPv4
if [ -z "$ipv6" ]; then
ipp=$(echo "$ifconfig_pool_remote_ip" | cut -d. -f4)
if ! [ "$ipp" -ge 2 -a "$ipp" -le 254 ] 2>/dev/null; then
echo "Invalid IPv4 part."
exit 1
fi
hexipp=$(printf '%x' $ipp)
ipv6="$prefix$hexipp"
fi

# Delete proxy rule
/sbin/ip -6 neigh del proxy $ipv6 dev eth0

Як можна було побачити в конфіги сервера запускати ми його будемо під пользоателем vpn, а тому нам треба додати користувача

# useradd vpn

і дозволити користувачеві sudo на наші скрипти додавши в /etc/sudoers(не правте його руками відкриваючи безпосередньо в редакторі, викликайте visudo, що б перед збереженням перевірити коректність файлу!):

Defaults:vpn env_keep += "ifconfig_pool_remote_ip common_name"
vpn ALL=NOPASSWD: /etc/openvpn/server-clientconnect.sh
vpn ALL=NOPASSWD: /etc/openvpn/server-clientdisconnect.sh

Тепер включимо ndp(Neighbor Discovery Protocol), який нам потрібен для того, що б наші хости знаходили по IPv6 один одного і що б вони були доступні з інтернету за своїми адресами, додавши в /etc/sysctl.conf(або в окремий файл /etc/sysctl.d/, за вашим бажанням) рядки:

net.ipv6.conf.all.forwarding=1
net.ipv6.conf.all.proxy_ndp = 1

і виконавши
# sysctl -p

Налаштуємо адреси для окремої машини створивши файл з іменем хоста який буде підключатися(ім'я повинне збігатися з ім'ям використовувався при створенні сертифіката для машини), нехай це буде abyrvalg-laptop в /etc/openvpn/ccd

/etc/openvpn/ccd/abyrvalg-laptop
ifconfig-push 10.18.0.101 255.255.255.0
ifconfig-ipv6-push 2001:NNNN:NNNN:NNNN:80::1001/112 2001:NNNN:NNNN:NNNN:80::1

Першим з IPv6-адреси вказано адресу який буде видаватися хосту, другий адреса його гейти.

Сервер готовий, давайте напишемо конфіг для клієнта:

abyrvalg-laptop.conf
# Client mode
client

# IPv6 tunnel
dev tap

# Protocol TCP
proto udp

# Address/Port of VPN server
remote SERVER_IP 8149

# Don't bind to local port/address
nobind

# Don't need to re-read keys and re-create tun at restart
persist-key
persist-tun

# User/Group
;user nobody
;group nobody

# Remote peer must have a signed certificate
remote-cert-tls server
ns-cert-type server

# Enable compression
comp-lzo
ca ca.crt
cert abyrvalg-laptop.crt
key abyrvalg-laptop.key
sndbuf 0
rcvbuf 0

І спробуємо в ручному режимі запустити сервер і клієнт для тестів. Я виходжу з того, що конфіг-файл сервера і файли сертифікатів лежать у вас в /etc/openvpn на сервері і конфіг-файл для клієнта разом з сертифікатами лежать в /etc/openvpn на клієнті, конфіги при цьому іменуються server.conf на сервері і ipv6.conf на клієнті

На сервері робимо:

# cd /etc/openvpn
# openvpn ./server.conf

на клієнті

# cd /etc/openvpn
# openvpn ./ipv6.conf

Якщо все зроблено правильно, то на клієнті команда ip -6 a s dev tap0 покаже нам щось типу

48: tap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UNKNOWN qlen 100
inet6 2001:NNNN:NNNN:NNNN:80::1001/112 scope global


і ping6 -c 4 ipv6.google.com
покаже:

PING ipv6.google.com(lr-in-x8a.1e100.net) 56 data bytes
64 bytes from lr-in-x8a.1e100.net: icmp_seq=1 ttl=46 time=110 ms
64 bytes from lr-in-x8a.1e100.net: icmp_seq=2 ttl=46 time=113 ms
64 bytes from lr-in-x8a.1e100.net: icmp_seq=3 ttl=46 time=110 ms
64 bytes from lr-in-x8a.1e100.net: icmp_seq=4 ttl=46 time=110 ms

--- ipv6.google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 110.586/111.367/113.285/1.183 ms

Вуаля! У нас тепер на нашому ноутбуці або стационарнике є нормальний IPv6, без тунельних брокерів.

Для додавання старту openvpn при завантаженні на ваших системах використовувати штатні засоби, залежно від дистрибутива вони можуть різнитися.

При налаштуванні і написанні використана данная стаття, там же ви можете подивитися на приклади генерації ключів для OpenVPN, якщо до цього їх не генерували. На відміну від оригінальної статті я використовую udp, а не tcp і tap, а не tun-девайси.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.