动态多点 VPN (DMVPN)

来自 Alpine Linux

https://alpinelinux.cn/aboutWhy the Name Alpine? 中提到

Cisco DMVPN 的第一个开源实现 OpenNHRP 是为 Alpine Linux 编写的。[1]

因此,本文档的目的是成为 Linux DMVPN 设置的参考,包含客户端使用 DMVPN 所需的所有网络服务(DNS、防火墙等)。 小型办公室服务 提供额外的服务,例如客户端的 DHCP、HTTP 代理和基本的 SIP 电话系统。

术语

NBMA
非广播多路访问 网络,如 RFC 2332 中所述
Hub
执行 NBMA 云内下一跳解析协议服务的下一跳服务器 (NHS)。
Spoke
下一跳解析协议客户端 (NHC),它发起各种类型的 NHRP 请求,以便获得对 NHRP 服务的访问权限。
提示: 在撰写本文时,构建 DMVPN 推荐的最低 Alpine 版本应为 2.4.11。请勿使用 2.5.x 或 2.6.0,因为内核存在隧道内 IP 分片问题。Alpine 3.0 在 getprotobyname() 中也存在 Musl 问题。Alpine 2.7.x 已经过全面测试,并且 3.0.3 至今未显示任何问题。
注意: 本文档假定所有 Alpine 安装均以 无盘模式 运行,并且配置保存在 USB 密钥上

硬件

如果您需要千兆位吞吐量,则应选择具有 AES-NISHA 扩展 的处理器。

提取证书

我们将使用证书用于 DMVPN 和 OpenVPN(RoadWarrior 客户端)。如果您需要生成自己的证书,请参阅 Generating_SSL_certs_with_ACF。您应该为此目的使用单独的机器。如果您在 Windows 机器上下载了证书,则可以使用 WinSCP 将它们复制到 DMVPN 设备上。

以下是从 pfx 文件中提取证书的通用说明

openssl pkcs12 -in cert.pfx -cacerts -nokeys -out cacert.pem openssl pkcs12 -in cert.pfx -nocerts -nodes -out serverkey.pem openssl pkcs12 -in cert.pfx -nokeys -clcerts -out cert.pem

为您的证书文件设置适当的权限

chmod 600 *.pem *.pfx

Spoke 节点

本地 Spoke 节点网络支持多个 ISP 连接,以及冗余的第 2 层交换机。至少需要一个支持 802.1q 的交换机,第二个是可选的,用于冗余目的。典型的 Spoke 节点网络如下所示

启动 Alpine USB

按照 Create_a_Bootable_USB 上的说明,了解如何创建可启动的 USB。

Alpine 设置

我们将按如下方式设置网络接口

接口 描述 子网
bond0.3 管理 10.1.0.129/26
bond0.101 LAN 10.1.0.0/25
bond0.256 来自 ISP1 的互联网 从 ISP 分配
bond0.257 来自 ISP2 的互联网 从 ISP 分配
bond0.620 wifi 代理和 dmvpn spoke 节点之间的传输 10.1.0.252/30
bond0.701 WiFi 客户端(无法访问 DMVPN 网络) 172.17.48.0/24
bond0.1101 语音 10.2.0.0/24

setup-alpine

您将被提示类似以下内容... 关于您可以输入的内容的建议...
选择键盘布局 [none] 输入适合您的布局
选择变体 输入适合您的布局(如果提示)
输入系统主机名(短格式,例如“foo”)[localhost] 输入主机名,例如 vpnc
可用接口为:eth0
输入“?”以获取有关桥接、链路聚合和 VLAN 的帮助。
您要初始化哪一个?(或“?”完成)
输入 bond0.101
可用的链路聚合从属设备为:eth0 eth1
您要将哪些从属设备添加到 bond0?(或“done”)[eth0]
eth0 eth1
bond0 的 IP 地址?(或“dhcp”、“none”、“?”)[none] 按 Enter 键确认“none”
bond0.101 的 IP 地址?(或“dhcp”、“none”、“?”)[dhcp] 输入您的 LAN 接口的 IP 地址,例如 10.1.0.1
子网掩码?[255.255.255.0] 按 Enter 键确认“255.255.255.0”或键入另一个合适的子网掩码
网关?(或“none”)[none] 按 Enter 键确认“none”
您要进行任何手动网络配置吗?[no] yes
为 bond0.620、bond0.701、bond0.1101、bond0.256 和 bond0.257(可选)接口复制 bond0.101 配置。
设置多个网关时,不要忘记为 ISP 接口添加网关和指标值。
保存并关闭文件 (:wq)
DNS 域名?(例如“bar.com”)[] 输入您的内联网域名,例如, example.net
DNS 名称服务器?[] 8.8.8.8 8.8.4.4 (稍后我们将更改它们)
正在更改 root 密码
新密码
为控制台输入安全密码
重新输入密码 重新输入上述密码
您所在的时区?(“?”表示列表)[UTC] 按 Enter 键确认“UTC”
HTTP/FTP 代理 URL?(例如“http://proxy:8080”或“none”)[none] 按 Enter 键确认“none”
输入镜像编号 (1-9) 或要添加的 URL(或 r/f/e/done)[f] 选择离您较近的镜像并按 Enter 键
哪个 SSH 服务器?(“openssh”、“dropbear”或“none”)[openssh] 按 Enter 键确认“openssh”
要运行哪个 NTP 客户端?(“openntpd”、“chrony”或“none”)[chrony] 按 Enter 键确认“chrony”
您想使用哪些磁盘?(或“?”表示帮助或“none”)[none] 按 Enter 键确认“none”或根据需要键入“none”
输入存储配置的位置(“floppy”、“usb”或“none”)[usb] 按 Enter 键确认“usb”
输入 apk 缓存目录(或“?”或“none”)[/media/usb/cache] 按 Enter 键确认“/media/usb/cache”

网络配置

更新网络配置。

使用您喜欢的编辑器打开 /etc/network/interfaces 并添加接口

内容 /etc/network/interfaces

... auto bond0.101 iface bond0.101 inet static address 10.1.0.1 netmask 255.255.255.192 auto bond0.620 iface bond0.620 inet static address 10.1.0.253 netmask 255.255.255.252 auto bond0.701 iface bond0.101 inet static address 172.17.48.1 netmask 255.255.255.0 auto bond0.1101 iface bond0.101 inet static address 10.2.0.1 netmask 255.255.255.0 auto bond0.256 iface bond0.256 inet static address <%ISP1_IP_ADDRESS%> netmask <%ISP1_NETMASK%> auto bond0.257 iface bond0.257 inet static address <%ISP2_IP_ADDRESS%> netmask <%ISP2_NETMASK%>

链路聚合

更新链路聚合配置。

使用您喜欢的编辑器打开 /etc/network/interfaces 并将 bond-modebond-miimonbond-updelay 参数添加到 bond0

内容 /etc/network/interfaces

auto bond0 iface bond0 inet manual bond-slaves eth0 eth1 bond-mode balance-tlb bond-miimon 100 bond-updelay 500 ...

启动新的链路聚合设置

ifdown bond0 ifup bond0


物理安装

此时,如果您尚未连接 VPN Spoke 节点到网络,则可以连接了。请设置一个支持 802.1q 的交换机,其中包含 AlpineSetup 部分中列出的 VLAN。完成后,在一个端口上标记所有 VLAN。将该端口连接到 eth0。然后,将您的第一个 ISP 的 CPE 连接到具有 VLAN 256 未标记的交换机端口。

SSH

删除密码身份验证和 DNS 反向查找

sed -i "s/.PasswordAuthentication yes/PasswordAuthentication no/" /etc/ssh/sshd_config sed -i "s/.UseDNS yes/UseDNS no/" /etc/ssh/sshd_config

重启 ssh

rc-service sshd restart

NTP 服务器

为了让连接的设备再次与此主机同步时间,我们需要对 chrony 配置进行一些修改。
将 'allow all' 添加到 '/etc/chrony/chrony.conf' 的末尾,以便文件看起来像这样

内容 /etc/chrony/chrony.conf

server pool.ntp.org initstepslew 10 pool.ntp.org commandkey 10 keyfile /etc/chrony/chrony.keys driftfile /etc/chrony/chrony.drift allow all

重启 chronyd 以使更改生效

rc-service chronyd restart

递归 DNS

安装软件包

apk add -U unbound

使用您喜欢的编辑器打开 /etc/unbound/unbound.conf 并添加以下配置。如果您有要 unbound 解析但仅在您的网络内部的域名,则存在 stub-zone 节

内容 /etc/unbound/unbound.conf

server: verbosity: 1 interface: 10.1.0.1 do-ip4: yes do-ip6: no do-udp: yes do-tcp: yes do-daemonize: yes access-control: 10.1.0.0/16 allow access-control: 127.0.0.0/8 allow do-not-query-localhost: no root-hints: "/etc/unbound/root.hints" stub-zone: name: "location1.example.net" stub-addr: 10.1.0.2 stub-zone: name: "example.net" stub-addr: 172.16.255.1 stub-addr: 172.16.255.2 stub-addr: 172.16.255.3 stub-addr: 172.16.255.4 stub-addr: 172.16.255.5 stub-addr: 172.16.255.7 stub-zone: name: "example2.net" stub-addr: 172.16.255.1 stub-addr: 172.16.255.2 stub-addr: 172.16.255.3 stub-addr: 172.16.255.4 stub-addr: 172.16.255.5 stub-addr: 172.16.255.7

启动 unbound 并在此主机上开始使用 unbound

rc-service unbound start rc-update add unbound echo nameserver 10.1.0.1 > /etc/resolv.conf

GRE 隧道

使用您喜欢的编辑器打开 /etc/network/interfaces 并添加以下内容

内容 /etc/network/interfaces

auto gre1 iface gre1 inet static pre-up ip tunnel add $IFACE mode gre ttl 64 tos inherit key 12.34.56.78 || true address 172.16.1.1 netmask 255.255.0.0 post-down ip tunnel del $IFACE || true

启动新的 gre1 接口

ifup gre1

IPSEC

安装软件包

apk add ipsec-tools

使用您喜欢的编辑器创建 /etc/ipsec.conf 并将内容设置为以下内容

内容 /etc/ipsec.conf

spdflush; spdadd 0.0.0.0/0 0.0.0.0/0 gre -P out ipsec esp/transport//require; spdadd 0.0.0.0/0 0.0.0.0/0 gre -P in ipsec esp/transport//require;

创建缺失的目录

mkdir /etc/racoon/

将您的 pfx 提取到 /etc/racoon,使用文件名 ca.pemcert.pemkey.pem (请参阅 上面的说明)。

使用您喜欢的编辑器创建 /etc/racoon/racoon.conf 并将内容设置为以下内容

内容 /etc/racoon/racoon.conf

path certificate "/etc/racoon/"; remote anonymous { exchange_mode main; lifetime time 2 hour; certificate_type x509 "/etc/racoon/cert.pem" "/etc/racoon/key.pem"; ca_type x509 "/etc/racoon/ca.pem"; my_identifier asn1dn; nat_traversal on; script "/etc/opennhrp/racoon-ph1dead.sh" phase1_dead; dpd_delay 120; proposal { encryption_algorithm aes 256; hash_algorithm sha1; authentication_method rsasig; dh_group modp4096; } proposal { encryption_algorithm aes 256; hash_algorithm sha1; authentication_method rsasig; dh_group 2; } } sainfo anonymous { pfs_group 2; lifetime time 2 hour; encryption_algorithm aes 256; authentication_algorithm hmac_sha1; compression_algorithm deflate; }

编辑 /etc/conf.d/racoon 并取消设置 RACOON_PSK_FILE

内容 /etc/conf.d/racoon

... RACOON_PSK_FILE= ...

启动服务

rc-service racoon start rc-update add racoon

下一跳解析协议 (NHRP)

安装软件包

apk add opennhrp

使用您喜欢的编辑器打开 /etc/opennhrp/opennhrp.conf 并将内容更改为以下内容

内容 /etc/opennhrp/opennhrp.conf

interface gre1 dynamic-map 172.16.0.0/16 hub.example.com shortcut redirect non-caching interface bond0.8 shortcut-destination interface bond0.64 shortcut-destination interface bond0.620 shortcut-destination

您必须为每个 hub 节点 IP 地址设置 DNS A 记录 hub.example.com

使用您喜欢的编辑器打开 /etc/opennhrp/opennhrp-script 并将内容更改为以下内容

内容 /etc/opennhrp/opennhrp-script

#!/bin/sh MYAS=$(sed -n 's/router bgp \(\d*\)/\1/p' < /etc/quagga/bgpd.conf) case $1 in interface-up) echo "Interface $NHRP_INTERFACE is up" if [ "$NHRP_INTERFACE" = "gre1" ]; then ip route flush proto 42 dev $NHRP_INTERFACE ip neigh flush dev $NHRP_INTERFACE vtysh -d bgpd \ -c "configure terminal" \ -c "router bgp $MYAS" \ -c "no neighbor core" \ -c "neighbor core peer-group" fi  ;; peer-register)  ;; peer-up) if [ -n "$NHRP_DESTMTU" ]; then ARGS=`ip route get $NHRP_DESTNBMA from $NHRP_SRCNBMA | head -1` ip route add $ARGS proto 42 mtu $NHRP_DESTMTU fi echo "Create link from $NHRP_SRCADDR ($NHRP_SRCNBMA) to $NHRP_DESTADDR ($NHRP_DESTNBMA)" racoonctl establish-sa -w isakmp inet $NHRP_SRCNBMA $NHRP_DESTNBMA || exit 1 racoonctl establish-sa -w esp inet $NHRP_SRCNBMA $NHRP_DESTNBMA gre || exit 1  ;; peer-down) echo "Delete link from $NHRP_SRCADDR ($NHRP_SRCNBMA) to $NHRP_DESTADDR ($NHRP_DESTNBMA)" racoonctl delete-sa isakmp inet $NHRP_SRCNBMA $NHRP_DESTNBMA ip route del $NHRP_DESTNBMA src $NHRP_SRCNBMA proto 42  ;; nhs-up) echo "NHS UP $NHRP_DESTADDR" ( flock -x 200 vtysh -d bgpd \ -c "configure terminal" \ -c "router bgp $MYAS" \ -c "neighbor $NHRP_DESTADDR remote-as 65000" \ -c "neighbor $NHRP_DESTADDR peer-group core" \ -c "exit" \ -c "exit" \ -c "clear bgp $NHRP_DESTADDR" ) 200>/var/lock/opennhrp-script.lock  ;; nhs-down) ( flock -x 200 vtysh -d bgpd \ -c "configure terminal" \ -c "router bgp $MYAS" \ -c "no neighbor $NHRP_DESTADDR" ) 200>/var/lock/opennhrp-script.lock  ;; route-up) echo "Route $NHRP_DESTADDR/$NHRP_DESTPREFIX is up" ip route replace $NHRP_DESTADDR/$NHRP_DESTPREFIX proto 42 via $NHRP_NEXTHOP dev $NHRP_INTERFACE ip route flush cache  ;; route-down) echo "Route $NHRP_DESTADDR/$NHRP_DESTPREFIX is down" ip route del $NHRP_DESTADDR/$NHRP_DESTPREFIX proto 42 ip route flush cache  ;; esac exit 0

使其可执行并启动服务

chmod +x /etc/opennhrp/opennhrp-script rc-service opennhrp start rc-update add opennhrp

BGP

安装软件包

apk add quagga touch /etc/quagga/zebra.conf

使用您喜欢的编辑器打开 /etc/quagga/bgpd.conf 并将内容更改为以下内容(将 strongpassword 替换为您选择的密码,并将 %HUB_GRE_IP% 替换为 Hub 节点 GRE IP 地址)

  • 为您在 NBMA 云中拥有的每个 Hub 主机添加行 neighbor %HUB_GRE_IP% remote-as 65000

内容 /etc/quagga/bgpd.conf

password strongpassword enable password strongpassword log syslog access-list 1 remark Command line access authorized IP access-list 1 permit 127.0.0.1 line vty access-class 1 hostname vpnc.example.net router bgp 65001 bgp router-id 172.16.1.1 network 10.1.0.0/16 neighbor %HUB_GRE_IP% remote-as 65000 neighbor %HUB_GRE_IP% remote-as 65000 ...

启动服务

rc-service bgpd start rc-update add bgpd

OpenVPN

安装软件包

echo tun >> /etc/modules modprobe tun apk add openvpn openssl openssl dhparam -out /etc/openvpn/dh1024.pem 1024

配置 openvpn

内容 /etc/openvpn/openvpn.conf

dev tun proto udp port 1194 server 10.1.128.0 255.255.255.0 push "route 10.0.0.0 255.0.0.0" push "dhcp-option DNS 10.1.0.1" tls-server ca /etc/openvpn/cacert.pem cert /etc/openvpn/servercert.pem key /etc/openvpn/serverkey.pem crl-verify /etc/openvpn/crl.pem dh /etc/openvpn/dh1024.pem persist-key persist-tun keepalive 10 120 comp-lzo status /var/log/openvpn.status mute 20 verb 3

启动服务

rc-service openvpn start rc-update add openvpn

防火墙

安装软件包

apk add awall

启用 IP 转发

sysctl -w net.ipv4.ip_forward=1 sed -i 's/.*net\.ipv4\.ip_forward.*$/net.ipv4.ip_forward = 1/g' /etc/sysctl.conf

使用您喜欢的编辑器,编辑以下文件并将其内容设置为如下所示


内容 /etc/awall/optional/params.json

{ "description": "params", "variable": { "B_IF": "bond0.8", "C_IF": "bond0.64", "DE_IF": "bond0.620", "ISP1_IF": "bond0.256", "ISP2_IF": "bond0.257" } }


内容 /etc/awall/optional/internet-host.json

{ "description": "Internet host", "import": "params", "zone": { "E": { "iface": [ "$ISP1_IF", "$ISP2_IF" ] }, "ISP1": { "iface": "$ISP1_IF" }, "ISP2": { "iface": "$ISP2_IF" } }, "filter": [ { "in": "E", "service": "ping", "action": "accept", "flow-limit": { "count": 10, "interval": 6 } }, { "in": "E", "out": "_fw", "service": [ "ssh", "https" ], "action": "accept", "conn-limit": { "count": 3, "interval": 60 } }, { "in": "_fw", "out": "E", "service": [ "dns", "http", "ntp" ], "action": "accept" }, { "in": "_fw", "service": [ "ping", "ssh" ], "action": "accept" } ] }


内容 /etc/awall/optional/openvpn.json

{ "description": "OpenVPN 支持", "import": "internet-host", "service": { "openvpn": { "proto": "udp", "port": 1194 } }, "filter": [ { "in": "E", "out": "_fw", "service": "openvpn", "action": "accept" } ] }


内容 /etc/awall/optional/clampmss.json

{ "description": "处理害怕 ICMP 的 ISP", "import": "internet-host", "clamp-mss": [ { "out": "E" } ] }


内容 /etc/awall/optional/mark.json

{ "description": "根据 ISP 标记流量", "import": [ "params", "internet-host" ], "route-track": [ { "out": "ISP1", "mark": 1 }, { "out": "ISP2", "mark": 2 } ] }


内容 /etc/awall/optional/dmvpn.json

{ "description": "DMVPN 路由器", "import": "internet-host", "variable": { "A_ADDR": [ "10.0.0.0/8", "172.16.0.0/16" ] }, "zone": { "A": { "addr": "$A_ADDR", "iface": "gre1" } }, "filter": [ { "in": "E", "out": "_fw", "service": "ipsec", "action": "accept" }, { "in": "_fw", "out": "E", "service": "ipsec", "action": "accept" }, { "in": "E", "out": "_fw", "ipsec": "in", "service": "gre", "action": "accept" }, { "in": "_fw", "out": "E", "ipsec": "out", "service": "gre", "action": "accept" }, { "in": "_fw", "out": "A", "service": "bgp", "action": "accept" }, { "in": "A", "out": "_fw", "service": "bgp", "action": "accept"}, { "out": "E", "dest": "$A_ADDR", "action": "reject" } ] }

内容 /etc/awall/optional/vpnc.json

{ "description": "VPNc", "import": [ "params", "internet-host", "dmvpn" ], "zone": { "B": { "iface": "$B_IF" }, "C": { "iface": "$C_IF" }, "DE": { "iface": "$DE_IF" } }, "policy": [ { "in": "A", "action": "accept" }, { "in": "B", "out": "A", "action": "accept" }, { "in": "C", "out": [ "A", "E" ], "action": "accept" }, { "in": "DE", "out": "E", "action": "accept" }, { "in": "E", "action": "drop" }, { "in": "_fw", "out": "A", "action": "accept" } ], "snat": [ { "out": "E" } ], "filter": [ { "in": "A", "out": "_fw", "service": [ "ping", "ssh", "http", "https" ], "action": "accept" }, { "in": [ "B", "C" ], "out": "_fw", "service": [ "dns", "ntp", "http", "https", "ssh" ], "action": "accept" }, { "in": "_fw", "out": [ "B", "C" ], "service": [ "dns", "ntp" ], "action": "accept" }, { "in": [ "A", "B", "C" ], "out": "_fw", "proto": "icmp", "action": "accept" }, { "out": "DE", "service": [ "ssh", "http", "https", "ping" ], "action": "accept" } ] }

激活防火墙

modprobe ip_tables modprobe iptable_nat awall enable clampmss awall enable openvpn awall enable vpnc awall activate -f rc-update add iptables

ISP 故障转移

安装软件包

apk add pingu echo -e "1\tisp1">> /etc/iproute2/rt_tables echo -e "2\tisp2">> /etc/iproute2/rt_tables

配置 pingu 以监视 bond0.256bond0.257 接口在 /etc/pingu/pingu.conf 中。将要监视的主机添加到 /etc/pingu/pingu.conf 以进行 ISP 故障转移,并绑定到主 ISP。我们还将 ping 超时设置为 4 秒。

内容 /etc/pingu/pingu.conf

timeout 4 required 2 retry 11 interface bond0.256 { # route-table must correspond with mark in /etc/awall/optional/mark.json route-table 1 fwmark 1 rule-priority 20000 # google dns ping 8.8.8.8 # opendns ping 208.67.222.222 } interface bond0.257 { # route-table must correspond with mark in /etc/awall/optional/mark.json route-table 2 fwmark 2 rule-priority 20000 }

确保我们可以从 LAN 访问公共 IP,方法是为我们的专用网络添加静态路由规则。编辑 /etc/pingu/route-rules

内容 /etc/pingu/route-rules

to 10.0.0.0/8 table main prio 1000 to 172.16.0.0/12 table main prio 1000

启动服务

rc-service pingu start rc-update add pingu

现在,如果两个主机都停止响应 ping,则 ISP-1 将被视为关闭,并且所有通过 bond0.256 的网关将从主路由表中删除。请注意,网关不会从路由表“1”中删除。这样做是为了我们可以继续尝试通过 bond0.256 进行 ping,以便我们可以检测到 ISP 重新在线。当 ISP 再次开始工作时,网关将再次添加回主路由表。

提交配置

提交配置

lbu ci

Hub 节点

我们将仅记录与 Spoke 节点设置不同的更改。

路由表

echo -e "42\tnhrp_shortcut\n43\tnhrp_mtu\n44\tquagga\n>> /etc/iproute2/rt_tables

添加以下“up”命令

内容 /etc/network/interfaces

auto gre1 ... up ip rule add lookup nhrp_shortcut pref 11000 up ip rule add lookup quagga pref 11001 up ip rule add lookup nhrp_mtu pref 11999

NHRP

在 Hub 2 上使用您喜欢的编辑器打开 /etc/opennhrp/opennhrp.conf 并将内容设置为如下所示

内容 /etc/opennhrp/opennhrp.conf

interface gre1 map %Hub1_GRE_IP%/%MaskBit% hub1.example.org route-table 44 shortcut redirect non-caching

在 Hub 1 上执行相同的操作,添加与 Hub 2 相关的数据。

使用您喜欢的编辑器打开 /etc/opennhrp/opennhrp-script 并将内容设置为如下所示

#!/bin/sh
case $1 in
interface-up)
	ip route flush proto 42 dev $NHRP_INTERFACE
	ip neigh flush dev $NHRP_INTERFACE
	;;
peer-register)
	CERT=`racoonctl get-cert inet $NHRP_SRCNBMA $NHRP_DESTNBMA | openssl x509 -inform der -text -noout | egrep -o "/OU=[^/]*(/[0-9]+)?" | cut -b 5-`
	if [ -z "`echo "$CERT" | grep "^GRE=$NHRP_DESTADDR"`" ]; then
		logger -t opennhrp-script -p auth.err "GRE registration of $NHRP_DESTADDR to $NHRP_DESTNBMA DENIED"
		exit 1
	fi
	logger -t opennhrp-script -p auth.info "GRE registration of $NHRP_DESTADDR to $NHRP_DESTNBMA authenticated"

	(
		flock -x 200
		
		AS=`echo "$CERT" | grep "^AS=" | cut -b 4-`
		vtysh -d bgpd -c "configure terminal" \
			-c "router bgp 65000" \
			-c "neighbor $NHRP_DESTADDR remote-as $AS" \
			-c "neighbor $NHRP_DESTADDR peer-group leaf" \
			-c "neighbor $NHRP_DESTADDR prefix-list net-$AS-in in"

		SEQ=5
		(echo "$CERT" | grep "^NET=" | cut -b 5-) | while read NET; do
			vtysh -d bgpd -c "configure terminal" \
				-c "ip prefix-list net-$AS-in seq $SEQ permit $NET le 26"
			SEQ=$(($SEQ+5))
		done
	) 200>/var/lock/opennhrp-script.lock
	;;
peer-up)
	echo "Create link from $NHRP_SRCADDR ($NHRP_SRCNBMA) to $NHRP_DESTADDR ($NHRP_DESTNBMA)"
	racoonctl establish-sa -w isakmp inet $NHRP_SRCNBMA $NHRP_DESTNBMA || exit 1
	racoonctl establish-sa -w esp inet $NHRP_SRCNBMA $NHRP_DESTNBMA gre || exit 1 

	CERT=`racoonctl get-cert inet $NHRP_SRCNBMA $NHRP_DESTNBMA | openssl x509 -inform der -text -noout | egrep -o "/OU=[^/]*(/[0-9]+)?" | cut -b 5-`
	if [ -z "`echo "$CERT" | grep "^GRE=$NHRP_DESTADDR"`" ]; then
		logger -p daemon.err "GRE mapping of $NHRP_DESTADDR to $NHRP_DESTNBMA DENIED"
		exit 1
	fi

	if [ -n "$NHRP_DESTMTU" ]; then
		ARGS=`ip route get $NHRP_DESTNBMA from $NHRP_SRCNBMA | head -1`
		ip route add $ARGS proto 42 mtu $NHRP_DESTMTU table nhrp_mtu
	fi
	;;
peer-down)
	echo "Delete link from $NHRP_SRCADDR ($NHRP_SRCNBMA) to $NHRP_DESTADDR ($NHRP_DESTNBMA)"
	if [ "$NHRP_PEER_DOWN_REASON" != "lower-down" ]; then
		racoonctl delete-sa isakmp inet $NHRP_SRCNBMA $NHRP_DESTNBMA
	fi
	ip route del $NHRP_DESTNBMA src $NHRP_SRCNBMA proto 42 table nhrp_mtu
	;;
route-up)
	echo "Route $NHRP_DESTADDR/$NHRP_DESTPREFIX is up"
	ip route replace $NHRP_DESTADDR/$NHRP_DESTPREFIX proto 42 via $NHRP_NEXTHOP dev $NHRP_INTERFACE table nhrp_shortcut
	ip route flush cache
	;;
route-down)
	echo "Route $NHRP_DESTADDR/$NHRP_DESTPREFIX is down"
	ip route del $NHRP_DESTADDR/$NHRP_DESTPREFIX proto 42 table nhrp_shortcut
	ip route flush cache
	;;
esac

exit 0

BGP

在 Hub 2 上使用您喜欢的编辑器打开 /etc/quagga/bgpd.conf 并将内容设置为如下所示

内容 /etc/quagga/bgpd.conf

password zebra enable password zebra log syslog router bgp 65000 bgp router-id %Hub2_GRE_IP% bgp deterministic-med network %GRE_NETWORK%/%MASK_BITS% neighbor hub peer-group neighbor hub next-hop-self neighbor hub route-map CORE-IN in neighbor spoke peer-group neighbor spoke passive neighbor spoke next-hop-self neighbor %Spoke1_GRE_IP% remote-as 65001 neighbor %Spoke1_GRE_IP% peer-group spoke neighbor %Spoke1_GRE_IP% prefix-list net-65001-in in ... ... ... neighbor hub remote-as 65000 neighbor %Hub1_GRE_IP% peer-group core ip prefix-list net-65001-in seq 5 permit 10.1.0.0/16 le 26 ... route-map CORE-IN permit 10 set metric +100

为您拥有的每个 spoke 节点添加行 neighbor %Spoke1_GRE_IP%...。在 Hub 1 上执行相同的操作,更改 Hub 2 的相关数据。

DMVPN 故障排除

路径 MTU 发现 (PMTUD) 故障

害怕 ICMP 的 ISP(这在某种程度上是合理的)通常只是盲目地在其路由器接口中添加 no ip unreachables,从而有效地创建 黑洞路由器,从而破坏 PMTUD,因为 ICMP 类型 3 代码 4 数据包(需要分片)被丢弃。ISAKMP 需要 PMTUD,它在 UDP 上运行(TCP 工作是因为它使用 CLAMPMSS)。

有关技术详细信息,请参阅 https://packetlife.net/blog/2008/oct/9/disabling-unreachables-breaks-pmtud/

PMTUD 也可能因 DSL 调制解调器/路由器配置错误或固件错误而损坏。关闭调制解调器本身上的防火墙或任何 VPN 直通功能可能会有所帮助。

您可以通过 ping DF 位集和标准 MTU 大小的数据包,以及 traceroute 到目的地的每个跃点,轻松检测到哪个主机是黑洞路由器

ping -M do -s 1472 %IP%

注意: “-M do” 需要 GNU ping,它存在于 iputils 软件包中

如果您没有收到响应(Echo-Response 或 Fragmentation-Needed),则表示防火墙正在丢弃 ICMP 数据包。如果它响应正常的 ping 数据包(DF 位清除),则很可能您遇到了黑洞路由器。

内核和 NHRP 路由缓存问题

待办事项...