Einen Linux-Router so konfigurieren, dass der Datenverkehr und DNS einiger LAN-Hosts über einen OpenVPN-Tunnel weitergeleitet wird?

Einen Linux-Router so konfigurieren, dass der Datenverkehr und DNS einiger LAN-Hosts über einen OpenVPN-Tunnel weitergeleitet wird?

Ich habe eine GNU/Linux-Box, die ich als Router für mein Heimnetzwerk eingerichtet habe. Ich habe drei Netzwerkschnittstellen ...

  • ppp0 ist die Upstream-Verbindung
  • lan ist das lokale Netzwerk
  • nordvpn ist der VPN-Tunnel

Ich verwende nftables für die Firewall und betreibe einen DNS-Server mit Cache (dnsmasq). DNS-Anfragen aus dem LAN werden abgefangen und stattdessen an den DNS-Server auf dem Router gesendet. So weit, so gut, aber ...

Standardmäßig routet NordVPNalleUpstream-Verkehr durch den VPN-Tunnel, und wenn er so konfiguriert ist, funktioniert er, aber ich möchte das nicht. Ich möchte, dass der meiste Verkehr zum Internet über die ppp0-Schnittstelle läuft, während der Verkehr von bestimmten LAN-Hosts stattdessen über das VPN gesendet wird. DNS-Anfragen für die Hosts, die das VPN verwenden, sollten an die DNS-Server des VPN-Anbieters und nicht an den lokalen Server gerichtet werden.

Ich habe verschiedene Artikel gelesen, in denen beschrieben wurde, wie man ähnliche (aber nicht identische) Dinge macht, und bisher habe ich es nicht geschafft, es zum Laufen zu bringen. Ich mache eindeutig mindestens eine Sache falsch. So wie ich es verstehe, sollte ich in der Lage sein, Pakete in der Firewall zu markieren und diese Pakete dann mithilfe einer benutzerdefinierten Routing-Tabelle über die NordVPN-Schnittstelle zu senden. Was ich bisher habe, ist Folgendes …

Ich habe die folgende Zeile hinzugefügt /etc/iproute2/rt_tables.

5     nordvpn

Um zu verhindern, dass OpenVPN seine eigenen Routen einrichtet, habe ich diese Zeilen hinzugefügt /etc/openvpn/client/nordvpn.conf.

route-noexec
script-security 2
route-up /etc/openvpn/client/mkroute.sh

Ich glaube, ich muss die Rückwärtspfadfilterung auf der NordVPN-Schnittstelle deaktivieren, damit alles funktioniert. Dies ist das Skript, das OpenVPN zum Einrichten meines Routings verwendet.

#!/bin/bash

TABLE="nordvpn"
MARK="0x5"

die() {
  echo "Error: $1"
  exit 1
}

[ $(id -u) -eq 0 ] || die "Not running as root"

ip route flush cache || echo "error 1"
ip route flush table "$TABLE" || echo "error 2"

ip route add 192.168.2.0/24 dev lan src 192.168.2.1 table "$TABLE" || echo "error 3"
ip route add $route_vpn_gateway dev lan src $ifconfig_local table "$TABLE" || echo "error 4"
ip route add default via $route_vpn_gateway dev "$dev" table "$TABLE" || echo "error 5"
ip rule delete fwmark "$MARK" || :
ip rule add fwmark "$MARK" lookup "$TABLE" || echo "error 6"
sysctl -w net.ipv4.conf.nordvpn.rp_filter=0 || echo "error 7"

Dies ist schließlich mein Nftables-Skript.

flush ruleset

define i_wan = ppp0
define i_nordvpn = nordvpn
define i_lan = lan

define p_dns = 53

define a4_nordvpn_dns_1 = 103.86.96.100
define m_nordvpn = 5

define h4_nimrod = 192.168.2.21

table ip ip4_firewall {

  set s_inet_nordvpn { type ipv4_addr; elements = { $h4_nimrod }; }

  chain c_here_to_wan { tcp flags syn tcp option maxseg size set rt mtu; accept; }
  chain c_here_to_nordvpn { tcp flags syn tcp option maxseg size set rt mtu; accept; }
  chain c_here_to_lan { accept; }
  chain c_wan_to_here { ip protocol icmp accept; drop; }
  chain c_wan_to_lan { ip protocol icmp accept; drop; }
  chain c_nordvpn_to_here { ip protocol icmp accept; drop; }
  chain c_nordvpn_to_lan { ip protocol icmp accept; drop; }
  chain c_lan_to_here { accept; }
  chain c_lan_to_wan { tcp flags syn tcp option maxseg size set rt mtu; accept; }
  chain c_lan_to_nordvpn { tcp flags syn tcp option maxseg size set rt mtu; accept; }

  chain preroute_nordvpn {
    udp dport $p_dns mark set $m_nordvpn dnat $a4_nordvpn_dns_1
    tcp dport $p_dns mark set $m_nordvpn dnat $a4_nordvpn_dns_1
    oif $i_wan mark set $m_nordvpn
  }

  chain prerouting { type nat hook prerouting priority -100
    ip saddr @s_inet_nordvpn goto preroute_nordvpn
    iif $i_lan oif $i_wan udp dport $p_dns redirect
    iif $i_lan oif $i_wan tcp dport $p_dns redirect
  }

  chain postrouting { type nat hook postrouting priority 100
    oif $i_nordvpn masquerade
    oif $i_wan snat <my public IP address>
  }

  chain input { type filter hook input priority 0; policy drop
    ct state established,related accept
    ct state invalid drop
    iif vmap {
      lo: accept,
      $i_wan : jump c_wan_to_here,
      $i_nordvpn : jump c_nordvpn_to_here,
      $i_lan : jump c_lan_to_here
    }
    log prefix "Unhandled input: " drop
  }

  chain output { type filter hook output priority 0; policy drop
    ct state established,related accept
    ct state invalid drop
    oif vmap {
      lo: accept,
      $i_wan : jump c_here_to_wan,
      $i_nordvpn : jump c_here_to_nordvpn,
      $i_lan : jump c_here_to_lan
    }
    log prefix "Unhandled output: " drop
  }

  chain forward { type filter hook forward priority 0; policy drop
    ct state established,related accept
    ct state invalid drop
    iif . oif vmap {
      $i_lan . $i_wan : jump c_lan_to_wan,
      $i_wan . $i_lan : jump c_wan_to_lan,
      $i_lan . $i_nordvpn : jump c_lan_to_nordvpn,
      $i_nordvpn . $i_lan : jump c_nordvpn_to_lan,
    }
    log prefix "Unhandled forward: " drop
  }
}

Nach der Konfiguration habe ich Folgendes.

[root@cerberus ~]# ip rule ls
0:      from all lookup local
32765:  from all fwmark 0x65 lookup nordvpn
32766:  from all lookup main
32767:  from all lookup default
[root@cerberus ~]# ip route ls
default dev ppp0 scope link 
10.0.0.1 dev ppp0 proto kernel scope link src <my public IP address> 
10.8.0.0/24 dev nordvpn proto kernel scope link src 10.8.0.12 
192.168.2.0/24 dev lan proto kernel scope link src 192.168.2.1 
[root@cerberus ~]# ip route ls table nordvpn
default via 10.8.0.1 dev nordvpn 
10.8.0.1 dev lan scope link src 10.8.0.12 
192.168.2.0/24 dev lan scope link src 192.168.2.1 
[root@cerberus ~]# ip rule ls
0:      from all lookup local
32764:  from all fwmark 0x5 lookup nordvpn
32766:  from all lookup main
32767:  from all lookup default

Wenn diese Option aktiviert ist, schlagen die DNS-Suchvorgänge der dem VPN zugewiesenen Clients fehl. Es scheint, dass die Anfragen über den VPN-Tunnel gesendet werden, aber die Antworten kommen in der Eingabekette und nicht in der Weiterleitungskette an und erreichen die Clients nicht. Was mache ich falsch?

Vielen Dank im Voraus für jede Hilfe :)

Antwort1

Versuche zu ändern:

  chain preroute_nordvpn {
    udp dport $p_dns mark set $m_nordvpn dnat $a4_nordvpn_dns_1
    tcp dport $p_dns mark set $m_nordvpn dnat $a4_nordvpn_dns_1
    oif $i_wan mark set $m_nordvpn
  }

  chain prerouting { type nat hook prerouting priority -100
    ip saddr @s_inet_nordvpn goto preroute_nordvpn
    iif $i_lan oif $i_wan udp dport $p_dns redirect
    iif $i_lan oif $i_wan tcp dport $p_dns redirect
  }

Zu:

  chain fwmark { type filter hook prerouting priority -150
    ip saddr @s_inet_nordvpn mark set $m_nordvpn
  }

  chain lan_dns {
    ip saddr @s_inet_nordvpn dnat $a4_nordvpn_dns_1
    redirect
  }

  chain lan_dnat {
    udp dport $p_dns goto lan_dns
    tcp dport $p_dns goto lan_dns
  }

  chain prerouting { type nat hook prerouting priority -100
    iif $i_lan goto lan_dnat
  }

verwandte Informationen