Di chuyển từ OpenVPN sang WireGuard để hợp nhất các mạng thành một mạng L2

Di chuyển từ OpenVPN sang WireGuard để hợp nhất các mạng thành một mạng L2

Tôi muốn chia sẻ kinh nghiệm của mình về việc kết hợp các mạng trong ba căn hộ cách xa nhau về mặt địa lý, mỗi căn hộ sử dụng bộ định tuyến với OpenWRT làm cổng, thành một mạng chung. Khi chọn phương pháp kết hợp mạng giữa L3 với định tuyến mạng con và L2 với cầu nối, khi tất cả các nút mạng sẽ nằm trong cùng một mạng con, phương pháp thứ hai sẽ được ưu tiên, phương pháp này khó định cấu hình hơn nhưng cung cấp nhiều cơ hội hơn, vì trong suốt việc sử dụng các công nghệ đã được lên kế hoạch trong mạng Wake-on-Lan và DLNA đã tạo.

Phần 1: Bối cảnh

OpenVPN ban đầu được chọn làm giao thức để thực hiện tác vụ này, vì thứ nhất, nó có thể tạo một thiết bị vòi có thể thêm vào cầu nối mà không gặp bất kỳ sự cố nào và thứ hai, OpenVPN hỗ trợ hoạt động qua giao thức TCP, điều này cũng rất quan trọng, bởi vì không có căn hộ nào có địa chỉ IP chuyên dụng và tôi không thể sử dụng STUN vì lý do nào đó mà ISP của tôi chặn các kết nối UDP đến từ mạng của họ, trong khi giao thức TCP cho phép tôi chuyển tiếp cổng máy chủ VPN trên VPS đã thuê bằng SSH. Có, cách tiếp cận này mang lại tải trọng lớn, vì dữ liệu được mã hóa hai lần, nhưng tôi không muốn đưa VPS vào mạng riêng của mình, vì vẫn có nguy cơ bên thứ ba giành quyền kiểm soát nó, do đó, có một thiết bị trên mạng gia đình là cực kỳ không mong muốn và nó đã được quyết định trả tiền cho bảo mật với chi phí lớn.

Để chuyển tiếp cổng trên bộ định tuyến mà nó được lên kế hoạch triển khai máy chủ, chương trình sshtunnel đã được sử dụng. Tôi sẽ không mô tả sự phức tạp trong cấu hình của nó - điều này được thực hiện khá dễ dàng, tôi chỉ lưu ý rằng nhiệm vụ của nó là chuyển tiếp cổng TCP 1194 từ bộ định tuyến sang VPS. Tiếp theo, máy chủ OpenVPN được định cấu hình trên thiết bị tap0 được kết nối với cầu br-lan. Sau khi kiểm tra kết nối với máy chủ mới được tạo từ máy tính xách tay, rõ ràng là ý tưởng chuyển tiếp cổng đã hợp lý và máy tính xách tay của tôi đã trở thành một thành viên của mạng của bộ định tuyến, mặc dù nó không ở trong đó.

Vấn đề vẫn còn nhỏ: cần phải phân phối địa chỉ IP trong các căn hộ khác nhau để chúng không xung đột và định cấu hình bộ định tuyến làm máy khách OpenVPN.
Các địa chỉ IP bộ định tuyến và phạm vi máy chủ DHCP sau đây đã được chọn:

  • 192.168.10.1 với phạm vi 192.168.10.2 - 192.168.10.80 cho máy chủ
  • 192.168.10.100 với phạm vi 192.168.10.101 - 192.168.10.149 cho một bộ định tuyến trong căn hộ số 2
  • 192.168.10.150 với phạm vi 192.168.10.151 - 192.168.10.199 cho một bộ định tuyến trong căn hộ số 3

Cũng cần phải gán chính xác các địa chỉ này cho các bộ định tuyến máy khách của máy chủ OpenVPN bằng cách thêm dòng vào cấu hình của nó:

ifconfig-pool-persist /etc/openvpn/ipp.txt 0

và thêm các dòng sau vào tệp /etc/openvpn/ipp.txt:

flat1_id 192.168.10.100
flat2_id 192.168.10.150

trong đó flat1_id và flat2_id là tên thiết bị được chỉ định khi tạo chứng chỉ để kết nối với OpenVPN

Tiếp theo, các máy khách OpenVPN được định cấu hình trên các bộ định tuyến, các thiết bị tap0 trên cả hai đã được thêm vào cầu br-lan. Ở giai đoạn này, mọi thứ dường như đã ổn định, vì cả ba mạng đều nhìn thấy nhau và hoạt động như một thể thống nhất. Tuy nhiên, một chi tiết không mấy dễ chịu đã bật ra: đôi khi các thiết bị có thể nhận được địa chỉ IP không phải từ bộ định tuyến của chúng, với tất cả các hậu quả sau đó. Vì một số lý do, bộ định tuyến ở một trong các căn hộ không có thời gian để phản hồi DHCPDISCOVER kịp thời và thiết bị đã nhận sai địa chỉ. Tôi nhận ra rằng tôi cần lọc các yêu cầu như vậy trong tap0 trên mỗi bộ định tuyến, nhưng hóa ra, iptables không thể hoạt động với thiết bị nếu nó là một phần của cầu nối và ebtables sẽ giải cứu tôi. Rất tiếc, nó không có trong chương trình cơ sở của tôi và tôi phải xây dựng lại hình ảnh cho từng thiết bị. Bằng cách này và thêm các dòng này vào /etc/rc.local của mỗi bộ định tuyến, vấn đề đã được giải quyết:

ebtables -A INPUT --in-interface tap0 --protocol ipv4 --ip-protocol udp --ip-destination-port 67:68 -j DROP
ebtables -A INPUT --in-interface tap0 --protocol ipv4 --ip-protocol udp --ip-source-port 67:68 -j DROP
ebtables -A FORWARD --out-interface tap0 --protocol ipv4 --ip-protocol udp --ip-destination-port 67:68 -j DROP
ebtables -A FORWARD --out-interface tap0 --protocol ipv4 --ip-protocol udp --ip-source-port 67:68 -j DROP

Cấu hình này kéo dài trong ba năm.

Phần 2: Giới thiệu WireGuard

Gần đây, Internet ngày càng nói nhiều về WireGuard, ngưỡng mộ sự đơn giản trong cấu hình, tốc độ truyền cao, ping thấp với khả năng bảo mật tương đương. Tìm kiếm thêm thông tin về nó cho thấy rõ ràng rằng nó không hoạt động với tư cách là thành viên cầu nối cũng như không hoạt động trên giao thức TCP, điều này khiến tôi nghĩ rằng vẫn không có lựa chọn thay thế nào cho OpenVPN dành cho tôi. Vì vậy, tôi đã ngừng tìm hiểu về WireGuard.

Vài ngày trước, tin tức đã lan truyền qua các tài nguyên bằng cách này hay cách khác liên quan đến CNTT rằng WireGuard cuối cùng sẽ được đưa vào nhân Linux, bắt đầu với phiên bản 5.6. Các bài báo, như mọi khi, ca ngợi WireGuard. Tôi lại lao vào tìm cách thay thế OpenVPN cũ tốt. Lần này tôi đụng phải bài viết này. Nó nói về việc tạo một đường hầm Ethernet qua L3 bằng GRE. Bài viết này đã cho tôi hy vọng. Vẫn chưa rõ phải làm gì với giao thức UDP. Việc tìm kiếm đã đưa tôi đến các bài báo về việc sử dụng socat kết hợp với đường hầm SSH để chuyển tiếp cổng UDP, tuy nhiên, họ lưu ý rằng phương pháp này chỉ hoạt động ở chế độ kết nối duy nhất, điều đó có nghĩa là không thể sử dụng nhiều máy khách VPN. Tôi nảy ra ý tưởng thiết lập máy chủ VPN trên VPS và thiết lập GRE cho khách hàng, nhưng hóa ra GRE không hỗ trợ mã hóa, điều này sẽ dẫn đến thực tế là nếu bên thứ ba có quyền truy cập vào máy chủ , tất cả lưu lượng truy cập giữa các mạng của tôi đều nằm trong tay họ, điều này hoàn toàn không phù hợp với tôi.

Một lần nữa, quyết định được đưa ra có lợi cho mã hóa dự phòng, bằng cách sử dụng VPN qua VPN theo sơ đồ sau:

VPN lớp XNUMX:
VPSngười phục vụ với địa chỉ nội bộ 192.168.30.1
MSkhách hàng VPS có địa chỉ nội bộ 192.168.30.2
MK2khách hàng VPS có địa chỉ nội bộ 192.168.30.3
MK3khách hàng VPS có địa chỉ nội bộ 192.168.30.4

VPN lớp XNUMX:
MSngười phục vụ với địa chỉ bên ngoài 192.168.30.2 và nội bộ 192.168.31.1
MK2khách hàng MS có địa chỉ 192.168.30.2 và có IP nội bộ là 192.168.31.2
MK3khách hàng MS có địa chỉ 192.168.30.2 và có IP nội bộ là 192.168.31.3

* MS - bộ định tuyến-máy chủ trong căn hộ 1, MK2 - bộ định tuyến trong căn hộ 2, MK3 - bộ định tuyến trong căn hộ 3
* Cấu hình thiết bị được công bố trong spoiler ở cuối bài viết.

Và như vậy, ping giữa các nút của mạng 192.168.31.0/24 đã đi, đã đến lúc chuyển sang thiết lập đường hầm GRE. Trước đó, để không bị mất quyền truy cập vào các bộ định tuyến, bạn nên thiết lập các đường hầm SSH để chuyển tiếp cổng 22 sang VPS, chẳng hạn như một bộ định tuyến từ căn hộ 10022 sẽ có sẵn trên cổng 2 của VPS và một bộ định tuyến từ căn hộ 11122 sẽ có sẵn trên cổng 3 của VPS Bộ định tuyến từ căn hộ XNUMX. Tốt nhất là định cấu hình chuyển tiếp với cùng một sshtunnel, vì nó sẽ khôi phục đường hầm trong trường hợp nó bị sập.

Đường hầm được định cấu hình, bạn có thể kết nối với SSH thông qua cổng được chuyển tiếp:

ssh root@МОЙ_VPS -p 10022

Tiếp theo, tắt OpenVPN:

/etc/init.d/openvpn stop

Bây giờ, hãy thiết lập đường hầm GRE trên bộ định tuyến từ căn hộ 2:

ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.2
ip link set grelan0 up

Và thêm giao diện đã tạo vào cây cầu:

brctl addif br-lan grelan0

Hãy thực hiện quy trình tương tự trên bộ định tuyến máy chủ:

ip link add grelan0 type gretap remote 192.168.31.2 local 192.168.31.1
ip link set grelan0 up

Ngoài ra, thêm giao diện đã tạo vào cầu nối:

brctl addif br-lan grelan0

bắt đầu từ thời điểm này, ping bắt đầu chuyển thành công sang mạng mới và tôi hài lòng đi uống cà phê. Sau đó, để xem mạng ở đầu dây bên kia hoạt động như thế nào, tôi thử SSH vào một trong các máy tính ở căn hộ 2, nhưng ứng dụng khách ssh bị treo mà không nhắc tôi nhập mật khẩu. Tôi cố gắng kết nối với máy tính này qua telnet trên cổng 22 và thấy một dòng mà bạn có thể hiểu rằng kết nối đang được thiết lập, máy chủ SSH đang phản hồi, nhưng vì lý do nào đó, nó không cho phép tôi truy cập.

$ telnet 192.168.10.110 22
SSH-2.0-OpenSSH_8.1

Tôi đang cố gắng kết nối với nó qua VNC và tôi thấy một màn hình đen. Tôi thuyết phục bản thân rằng vấn đề là ở máy tính từ xa, vì tôi có thể dễ dàng kết nối với bộ định tuyến từ căn hộ này bằng địa chỉ nội bộ. Tuy nhiên, tôi quyết định SSH vào máy tính này thông qua bộ định tuyến và ngạc nhiên khi thấy rằng kết nối thành công và máy tính từ xa hoạt động tốt nhưng cũng không kết nối được với máy tính của tôi.

Tôi lấy thiết bị grelan0 ra khỏi cầu nối và khởi động OpenVPN trên bộ định tuyến ở căn hộ 2 và đảm bảo rằng mạng hoạt động bình thường trở lại và các kết nối không bị rớt. Tìm kiếm, tôi bắt gặp các diễn đàn nơi mọi người phàn nàn về những vấn đề tương tự, nơi họ được khuyên nên tăng MTU. Không sớm nói hơn làm. Tuy nhiên, cho đến khi MTU được đặt thành giá trị đủ lớn là 7000 cho các thiết bị grepap, kết nối TCP bị ngắt hoặc truyền chậm đã được quan sát thấy. Do MTU cao cho gretap, MTU cho các kết nối WireGuard ở cấp độ thứ nhất và thứ hai được đặt tương ứng là 8000 và 7500.

Tôi đã thiết lập tương tự trên bộ định tuyến từ căn hộ 3, với điểm khác biệt duy nhất là giao diện gretap thứ hai có tên grelan1 đã được thêm vào bộ định tuyến máy chủ, giao diện này cũng được thêm vào cầu br-lan.

Mọi thứ đang hoạt động. Bây giờ bạn có thể đặt cụm grtap vào chế độ tự động tải. Đối với điều này:

Đặt những dòng này trong /etc/rc.local trên bộ định tuyến trong căn hộ 2:

ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.2
ip link set dev grelan0 mtu 7000
ip link set grelan0 up
brctl addif br-lan grelan0

Đã thêm phần này vào /etc/rc.local trên bộ định tuyến trong căn hộ 3:

ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.3
ip link set dev grelan0 mtu 7000
ip link set grelan0 up
brctl addif br-lan grelan0

Và trên bộ định tuyến máy chủ:

ip link add grelan0 type gretap remote 192.168.31.2 local 192.168.31.1
ip link set dev grelan0 mtu 7000
ip link set grelan0 up
brctl addif br-lan grelan0

ip link add grelan1 type gretap remote 192.168.31.3 local 192.168.31.1
ip link set dev grelan1 mtu 7000
ip link set grelan1 up
brctl addif br-lan grelan1

Sau khi khởi động lại các bộ định tuyến máy khách, tôi thấy rằng vì lý do nào đó mà chúng không kết nối được với máy chủ. Kết nối với SSH của họ (may mắn thay, trước đó tôi đã định cấu hình sshtunnel cho việc này), người ta phát hiện ra rằng WireGuard vì lý do nào đó đã tạo một tuyến đường cho điểm cuối, trong khi không chính xác. Vì vậy, đối với 192.168.30.2, bảng định tuyến đã được chỉ định trong bảng định tuyến thông qua giao diện pppoe-wan, nghĩa là thông qua Internet, mặc dù tuyến đường đến nó phải được định hướng thông qua giao diện wg0. Sau khi xóa tuyến đường này, kết nối đã được khôi phục. Tôi không thể tìm thấy hướng dẫn ở bất kỳ đâu về cách buộc WireGuard không tạo các tuyến này. Hơn nữa, tôi thậm chí còn không hiểu đây là một tính năng của OpenWRT hay của chính WireGuard. Không cần phải giải quyết vấn đề này trong một thời gian dài, tôi chỉ cần thêm vào cả hai bộ định tuyến một tập lệnh được lặp bởi bộ đếm thời gian, một dòng đã xóa tuyến đường này:

route del 192.168.30.2

Tổng kết

Tôi vẫn chưa từ chối hoàn toàn OpenVPN, vì đôi khi tôi cần kết nối với mạng mới từ máy tính xách tay hoặc điện thoại và việc thiết lập thiết bị gretap trên chúng nói chung là không thể, nhưng bất chấp điều này, tôi đã có lợi thế trong việc truyền dữ liệu tốc độ giữa các căn hộ và ví dụ như việc sử dụng VNC không còn bất tiện nữa. Ping giảm nhẹ, nhưng trở nên ổn định hơn:

Khi sử dụng OpenVPN:

[r0ck3r@desktop ~]$ ping -c 20 192.168.10.110
PING 192.168.10.110 (192.168.10.110) 56(84) bytes of data.
64 bytes from 192.168.10.110: icmp_seq=1 ttl=64 time=133 ms
...
64 bytes from 192.168.10.110: icmp_seq=20 ttl=64 time=125 ms

--- 192.168.10.110 ping statistics ---
20 packets transmitted, 20 received, 0% packet loss, time 19006ms
rtt min/avg/max/mdev = 124.722/126.152/136.907/3.065 ms

Khi sử dụng WireGuard:

[r0ck3r@desktop ~]$ ping -c 20 192.168.10.110
PING 192.168.10.110 (192.168.10.110) 56(84) bytes of data.
64 bytes from 192.168.10.110: icmp_seq=1 ttl=64 time=124 ms
...
64 bytes from 192.168.10.110: icmp_seq=20 ttl=64 time=124 ms
--- 192.168.10.110 ping statistics ---
20 packets transmitted, 20 received, 0% packet loss, time 19003ms
rtt min/avg/max/mdev = 123.954/124.423/126.708/0.675 ms

Nó chủ yếu bị ảnh hưởng bởi ping cao đến VPS, khoảng 61.5 mili giây

Tuy nhiên, tốc độ đã tăng lên đáng kể. Vì vậy, trong một căn hộ có bộ định tuyến-máy chủ, tôi có tốc độ kết nối Internet là 30 Mb/giây và ở các căn hộ khác là 5 Mb/giây. Đồng thời, khi sử dụng OpenVPN, tôi không thể đạt được tốc độ truyền dữ liệu giữa các mạng cao hơn 3,8 Mb/giây theo iperf, trong khi WireGuard đã “bơm” nó lên cùng tốc độ 5 Mb/giây.

Cấu hình WireGuard trên VPS[Interface] Address = 192.168.30.1/24
ListenPort = 51820
PrivateKey = <ЗАКРЫТЫЙ_КЛЮЧ_ДЛЯ_VPS>

[Peer] PublicKey = <ОТКРЫТЫЙ_КЛЮЧ_VPN_1_МС>
AllowedIPs = 192.168.30.2/32

[Peer] PublicKey = <ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК2>
AllowedIPs = 192.168.30.3/32

[Peer] PublicKey = <ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК3>
AllowedIPs = 192.168.30.4/32

Cấu hình WireGuard trên MS (được thêm vào /etc/config/network)

#VPN первого уровня - клиент
config interface 'wg0'
        option proto 'wireguard'
        list addresses '192.168.30.2/24'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_1_МС'
        option auto '1'
        option mtu '8000'

config wireguard_wg0
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_1_VPS'
        option endpoint_port '51820'
        option route_allowed_ips '1'
        option persistent_keepalive '25'
        list allowed_ips '192.168.30.0/24'
        option endpoint_host 'IP_АДРЕС_VPS'

#VPN второго уровня - сервер
config interface 'wg1'
        option proto 'wireguard'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_2_МС'
        option listen_port '51821'
        list addresses '192.168.31.1/24'
        option auto '1'
        option mtu '7500'

config wireguard_wg1
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК2'
        list allowed_ips '192.168.31.2'

config wireguard_wg1ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.3

        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК3'
        list allowed_ips '192.168.31.3'

Cấu hình WireGuard trên MK2 (được thêm vào /etc/config/network)

#VPN первого уровня - клиент
config interface 'wg0'
        option proto 'wireguard'
        list addresses '192.168.30.3/24'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_1_МК2'
        option auto '1'
        option mtu '8000'

config wireguard_wg0
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_1_VPS'
        option endpoint_port '51820'
        option persistent_keepalive '25'
        list allowed_ips '192.168.30.0/24'
        option endpoint_host 'IP_АДРЕС_VPS'

#VPN второго уровня - клиент
config interface 'wg1'
        option proto 'wireguard'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_2_МК2'
        list addresses '192.168.31.2/24'
        option auto '1'
        option listen_port '51821'
        option mtu '7500'

config wireguard_wg1
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МС'
        option endpoint_host '192.168.30.2'
        option endpoint_port '51821'
        option persistent_keepalive '25'
        list allowed_ips '192.168.31.0/24'

Cấu hình WireGuard trên MK3 (được thêm vào /etc/config/network)

#VPN первого уровня - клиент
config interface 'wg0'
        option proto 'wireguard'
        list addresses '192.168.30.4/24'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_1_МК3'
        option auto '1'
        option mtu '8000'

config wireguard_wg0
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_1_VPS'
        option endpoint_port '51820'
        option persistent_keepalive '25'
        list allowed_ips '192.168.30.0/24'
        option endpoint_host 'IP_АДРЕС_VPS'

#VPN второго уровня - клиент
config interface 'wg1'
        option proto 'wireguard'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_2_МК3'
        list addresses '192.168.31.3/24'
        option auto '1'
        option listen_port '51821'
        option mtu '7500'

config wireguard_wg1
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МС'
        option endpoint_host '192.168.30.2'
        option endpoint_port '51821'
        option persistent_keepalive '25'
        list allowed_ips '192.168.31.0/24'

Trong các cấu hình được mô tả cho VPN cấp hai, tôi chỉ định cổng 51821 cho các máy khách WireGuard. Về lý thuyết, điều này là không cần thiết vì máy khách sẽ thiết lập kết nối từ bất kỳ cổng không có đặc quyền miễn phí nào, nhưng tôi đã tạo nó để tất cả các kết nối đến có thể bị từ chối trên các giao diện wg0 của tất cả các bộ định tuyến, ngoại trừ các kết nối UDP đến trên cổng 51821.

Tôi hy vọng rằng bài viết sẽ hữu ích cho ai đó.

PS Ngoài ra, tôi muốn chia sẻ tập lệnh gửi cho tôi thông báo PUSH tới điện thoại của tôi trong ứng dụng WirePusher khi một thiết bị mới xuất hiện trên mạng của tôi. Đây là một liên kết đến kịch bản: github.com/r0ck3r/device_detect.

UPDATE: Cấu hình máy chủ và máy khách OpenVPN

máy chủ OpenVPN

client-to-client

ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/vpn-server.crt
dh /etc/openvpn/server/dh.pem
key /etc/openvpn/server/vpn-server.key

dev tap
ifconfig-pool-persist /etc/openvpn/ipp.txt 0
keepalive 10 60
proto tcp4
server-bridge 192.168.10.1 255.255.255.0 192.168.10.80 192.168.10.254
status /var/log/openvpn-status.log
verb 3
comp-lzo

Máy khách OpenVPN

client
tls-client
dev tap
proto tcp
remote VPS_IP 1194 # Change to your router's External IP
resolv-retry infinite
nobind

ca client/ca.crt
cert client/client.crt
key client/client.key
dh client/dh.pem

comp-lzo
persist-tun
persist-key
verb 3

Tôi đã sử dụng easy-rsa để tạo chứng chỉ.

Nguồn: www.habr.com

Thêm một lời nhận xét