本文章主要是用来描述如何使用vpp来搭建家庭网关。
首先vpp软件简介
VPP 平台是一个可扩展的框架,可提供开箱即用的生产质量交换机 / 路由器功能。它是思科矢量数据包处理(Vector Packet Processing,VPP)技术的开源版本:一种高性能的数据包处理堆栈,可以在商用 CPU 上运行。
FD.io 矢量数据包处理器使用矢量数据包处理算法。这个开源的 Linux Foundation 项目是 FD.io 项目的一部分。FD.io VPP 是一个 2 到 4 层网络堆栈。它运行在 Linux 用户空间,并能运行在多个商用 CPU 平台上。FD.io VPP 使用 DPDK 设备驱动程序和库来实现许多第 1 层的功能。
搭建家庭网关需要使用到的服务类型:ssh、DHCP、DNS等基础网络功能;
系统配置文件
文件名称:startup.conf
代码语言:javascript复制unix {
nodaemon
log /var/log/vpp/vpp.log
full-coredump
cli-listen /run/vpp/cli.sock
startup-config /setup.gate
poll-sleep-usec 100
gid vpp
}
api-segment {
gid vpp
}
dpdk {
dev 0000:03:00.0
dev 0000:14:00.0
etc.
}
plugins {
## Disable all plugins, selectively enable specific plugins
## YMMV, you may wish to enable other plugins (acl, etc.)
plugin default { disable }
plugin dhcp_plugin.so { enable }
plugin dns_plugin.so { enable }
plugin dpdk_plugin.so { enable }
plugin nat_plugin.so { enable }
plugin ping_plugin.so { enable }
## if you plan to use the time-based MAC filter
plugin mactime_plugin.so { enable }
plugin vmxnet3_plugin.so { enable }
}
2、 DHCP 配置文件
文件名:dhcpd.conf
注意:
如果您决定启用vpp-dns名称解析程序,请在dhcp服务器配置中将8.8.8.8替换为192.168.1.2。
代码语言:javascript复制subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.10 192.168.1.99;
option routers 192.168.1.1;
option domain-name-servers 8.8.8.8;
}
3、SSH配置文件
文件:/etc/ssh/sshd_config:
代码语言:javascript复制# What ports, IPs and protocols we listen for
Port <REDACTED-high-number-port>
# Change to no to disable tunnelled clear text passwords
PasswordAuthentication no
注意:
为了您自己的舒适和安全,不要允许密码验证,也不要回答端口22上的ssh请求。经验显示,在端口22上每小时有几次黑客攻击尝试,但在随机的高数量端口上没有。
4、Systemd configuration
在一个典型的家庭网关用例中,vpp拥有唯一一个广域网链接,并能接入公共互联网。像更新发行版软件这样简单的事情需要使用上面创建的“lstack”接口,并配置一个合理的上游DNS名称解析程序。
按照如下配置来配置/etc/systemd/resolved.conf
代码语言:javascript复制[Resolve]
DNS=8.8.8.8
#FallbackDNS=
#Domains=
#LLMNR=no
#MulticastDNS=no
#DNSSEC=no
#Cache=yes
#DNSStubListener=yes
Netplan configuration
该部分提供一个在ubuntu18.04上通过netplan来配置静态IP的一个参考,在现实使用中,需要根据实际情况调整。
/etc/netplan-01-netcfg.yaml:
代码语言:javascript复制# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
version: 2
renderer: networkd
ethernets:
enp4s0:
dhcp4: no
addresses: [192.168.2.254/24]
gateway4: 192.168.2.100
nameservers:
search: [my.local]
addresses: [8.8.8.8]
/etc/systemd/network-10.enp4s0.network:
代码语言:javascript复制[Match]
Name=enp4s0
[Link]
RequiredForOnline=no
[Network]
ConfigureWithoutCarrier=true
Address=192.168.2.254/24
请注意,我们为家庭网关选择了一个IP地址,该地址位于一个独立的不可路由子网上。这对于安装(并可能恢复)新的vpp软件非常方便。
VPP配置文件
代码语言:javascript复制define HOSTNAME vpp1
define TRUNK GigabitEthernet3/0/0
comment { Specific MAC address yields a constant IP address }
define TRUNK_MACADDR 48:f8:b3:00:01:01
define BVI_MACADDR 48:f8:b3:01:01:02
comment { inside subnet 192.168.<inside_subnet>.0/24 }
define INSIDE_SUBNET 1
# Adjust as needed to match PCI addresses of inside network ports
define INSIDE_PORT1 GigabitEthernet6/0/0
define INSIDE_PORT2 GigabitEthernet6/0/1
define INSIDE_PORT3 GigabitEthernet8/0/0
define INSIDE_PORT4 GigabitEthernet8/0/1
comment { feature selections }
define FEATURE_ADL uncomment
define FEATURE_NAT44 uncomment
define FEATURE_CNAT comment
define FEATURE_DNS comment
define FEATURE_IP6 comment
define FEATURE_IKE_RESPONDER comment
define FEATURE_MACTIME uncomment
define FEATURE_OVPN uncomment
define FEATURE_MODEM_ROUTE uncomment
exec /setup.tmpl
/setup.tmpl:
代码语言:javascript复制show macro
set int mac address $(TRUNK) $(TRUNK_MACADDR)
set dhcp client intfc $(TRUNK) hostname $(HOSTNAME)
set int state $(TRUNK) up
bvi create instance 0
set int mac address bvi0 $(BVI_MACADDR)
set int l2 bridge bvi0 1 bvi
set int ip address bvi0 192.168.$(INSIDE_SUBNET).1/24
set int state bvi0 up
set int l2 bridge $(INSIDE_PORT1) 1
set int state $(INSIDE_PORT1) up
set int l2 bridge $(INSIDE_PORT2) 1
set int state $(INSIDE_PORT2) up
set int l2 bridge $(INSIDE_PORT3) 1
set int state $(INSIDE_PORT3) up
set int l2 bridge $(INSIDE_PORT4) 1
set int state $(INSIDE_PORT4) up
comment { dhcp server and host-stack access }
create tap host-if-name lstack host-ip4-addr 192.168.$(INSIDE_SUBNET).2/24 host-ip4-gw 192.168.$(INSIDE_SUBNET).1
set int l2 bridge tap0 1
set int state tap0 up
service restart isc-dhcp-server
$(FEATURE_ADL) { bin adl_interface_enable_disable $(TRUNK) }
$(FEATURE_ADL) { ip table 1 }
$(FEATURE_ADL) { ip route add table 1 0.0.0.0/0 via local }
$(FEATURE_NAT44) { nat44 forwarding enable }
$(FEATURE_NAT44) { nat44 plugin enable sessions 63000 }
$(FEATURE_NAT44) { nat44 add interface address $(TRUNK) }
$(FEATURE_NAT44) { set interface nat44 in bvi0 out $(TRUNK) }
$(FEATURE_NAT44) { nat44 add static mapping local 192.168.$(INSIDE_SUBNET).2 22342 external $(TRUNK) 22342 tcp }
$(FEATURE_NAT44) { $(FEATURE_IKE_RESPONDER) { nat44 add identity mapping external $(TRUNK) udp 500 } }
$(FEATURE_NAT44) { $(FEATURE_IKE_RESPONDER) { nat44 add identity mapping external $(TRUNK) udp 4500 } }
$(FEATURE_NAT44) { $(FEATURE_DNS) { nat44 add static mapping local 192.168.$(INSIDE_SUBNET).2 53053 external $(TRUNK) 53053 udp } }
$(FEATURE_NAT44) { $(FEATURE_OVPN) { nat44 add static mapping local 192.168.$(INSIDE_SUBNET).2 37979 external $(TRUNK) 37979 udp } }
$(FEATURE_NAT44) { $(FEATURE_OVPN) { set interface feature bvi0 skipnat arc ip4-unicast } }
$(FEATURE_NAT44) { $(FEATURE_OVPN) { ip route add 192.168.10.0/24 via 192.168.$(INSIDE_SUBNET).2 } }
$(FEATURE_CNAT) { set cnat snat-policy none }
$(FEATURE_CNAT) { set cnat snat-policy addr $(TRUNK) }
$(FEATURE_CNAT) { set interface feature bvi0 cnat-snat-ip4 arc ip4-unicast }
$(FEATURE_CNAT) { cnat translation add proto tcp real $(TRUNK) 22342 to -> 192.168.$(INSIDE_SUBNET).2 22342 }
$(FEATURE_CNAT) { $(FEATURE_DNS) { cnat translation add proto udp real $(TRUNK) 53053 to -> 192.168.$(INSIDE_SUBNET).1 53053 } }
$(FEATURE_CNAT) { $(FEATURE_OVPN) { cnat translation add proto udp real $(TRUNK) 37979 to -> 192.168.$(INSIDE_SUBNET).2 37979 } }
$(FEATURE_CNAT) { $(FEATURE_OVPN) { set interface feature bvi0 skipnat arc ip4-unicast } }
$(FEATURE_CNAT) { $(FEATURE_OVPN) { ip route add 192.168.10.0/24 via 192.168.$(INSIDE_SUBNET).2 } }
$(FEATURE_DNS) { nat44 add identity mapping external $(TRUNK) udp 53053 }
$(FEATURE_DNS) { bin dns_name_server_add_del 8.8.8.8 }
$(FEATURE_DNS) { bin dns_enable_disable }
$(FEATURE_IP6) { set int ip6 table $(TRUNK) 0 }
$(FEATURE_IP6) { ip6 nd address autoconfig $(TRUNK) default-route }
$(FEATURE_IP6) { dhcp6 client $(TRUNK) }
$(FEATURE_IP6) { dhcp6 pd client $(TRUNK) prefix group hgw }
$(FEATURE_IP6) { set ip6 address bvi0 prefix group hgw ::1/64 }
$(FEATURE_IP6) { ip6 nd address autoconfig bvi0 default-route }
comment { iPhones seem to need lots of RA messages... }
$(FEATURE_IP6) { ip6 nd bvi0 ra-managed-config-flag ra-other-config-flag ra-interval 30 20 ra-lifetime 180 }
comment { ip6 nd bvi0 prefix 0::0/0 ra-lifetime 100000 }
comment { responder profile }
$(FEATURE_IKE_RESPONDER) { ikev2 profile add swan }
$(FEATURE_IKE_RESPONDER) { ikev2 profile set swan auth rsa-sig cert-file /home/dbarach/certs/swancert.pem }
$(FEATURE_IKE_RESPONDER) { set ikev2 local key /home/dbarach/certs/dorakey.pem }
$(FEATURE_IKE_RESPONDER) { ikev2 profile set swan id remote fqdn swan.barachs.net }
$(FEATURE_IKE_RESPONDER) { ikev2 profile set swan id local fqdn broiler2.barachs.net }
$(FEATURE_IKE_RESPONDER) { ikev2 profile set swan traffic-selector remote ip-range 192.168.1.0 - 192.168.1.255 port-range 0 - 65535 protocol 0 }
$(FEATURE_IKE_RESPONDER) { ikev2 profile set swan traffic-selector local ip-range 192.168.$(INSIDE_SUBNET).0 - 192.168.$(INSIDE_SUBNET).255 port-range 0 - 65535 protocol 0 }
$(FEATURE_IKE_RESPONDER) { create ipip tunnel src 73.120.164.15 dst 162.255.170.167 }
$(FEATURE_IKE_RESPONDER) { ikev2 profile set swan tunnel ipip0 }
$(FEATURE_IKE_RESPONDER) { set int mtu packet 1390 ipip0 }
$(FEATURE_IKE_RESPONDER) { set int unnum ipip0 use $(TRUNK) }
comment { if using the mactime plugin, configure it }
$(FEATURE_MACTIME) { bin mactime_add_del_range name roku mac 00:00:01:de:ad:be allow-static }
$(FEATURE_MACTIME) { bin mactime_enable_disable $(INSIDE_PORT1) }
$(FEATURE_MACTIME) { bin mactime_enable_disable $(INSIDE_PORT2) }
$(FEATURE_MACTIME) { bin mactime_enable_disable $(INSIDE_PORT3) }
$(FEATURE_MACTIME) { bin mactime_enable_disable $(INSIDE_PORT4) }
$(FEATURE_MODEM_ROUTE) { ip route add 192.168.100.1/32 via $(TRUNK) }
安装新的vpp应用软件
代码语言:javascript复制# nohup dpkg -i *.deb >/dev/null 2>&1 &
Build-host script
代码语言:javascript复制#!/bin/bash
buildroot=/scratch/vpp-workspace/build-root
if [ $1x = "testx" ] ; then
subdir="test"
ipaddr="192.168.2.48"
elif [ $1x = "foox" ] ; then
subdir="foo"
ipaddr="foo.some.net"
elif [ $1x = "barx" ] ; then
subdir="bar"
ipaddr="bar.some.net"
else
subdir="test"
ipaddr="192.168.2.48"
fi
echo Save current software...
ssh -p 22432 $ipaddr "rm -rf /gate_debians.prev"
ssh -p 22432 $ipaddr "mv /gate_debians /gate_debians.prev"
ssh -p 22432 $ipaddr "mkdir /gate_debians"
echo Copy new software to the gateway...
scp -P 22432 $buildroot/*.deb $ipaddr:/gate_debians
echo Install new software...
ssh -p 22432 $ipaddr "nohup /usr/local/bin/vpp-swupdate > /dev/null 2>&1 &"
for i in 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
do
echo Wait for $i seconds...
sleep 1
done
echo Try to access the device...
ssh -p 22432 -o ConnectTimeout=10 $ipaddr "tail -20 /var/log/syslog | grep Ping"
if [ $? == 0 ] ; then
echo Access test OK...
else
echo Access failed, wait for configuration restoration...
for i in 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
do
echo Wait for $i seconds...
sleep 1
done
echo Retry access test
ssh -p 22432 -o ConnectTimeout=10 $ipaddr "tail -20 /var/log/syslog | grep Ping"
if [ $? == 0 ] ; then
echo Access test OK, check syslog on the device
exit 1
else
echo Access test still fails, manual intervention required.
exit 2
fi
fi
exit 0
Target script
代码语言:javascript复制#!/bin/bash
logger "About to update vpp software..."
cd /gate_debians
service vpp stop
sudo dpkg -i *.deb >/dev/null 2>&1 &
sleep 20
logger "Ping connectivity test..."
for i in 1 2 3 4 5 6 7 8 9 10
do
ping -4 -c 1 yahoo.com
if [ $? == 0 ] ; then
logger "Ping test OK..."
exit 0
fi
done
logger "Ping test NOT OK, restore old software..."
rm -rf /gate_debians
mv /gate_debians.prev /gate_debians
cd /gate_debians
nohup sudo dpkg -i *.deb >/dev/null 2>&1 &
sleep 20
logger "Repeat connectivity test..."
for i in 1 2 3 4 5 6 7 8 9 10
do
ping -4 -c 1 yahoo.com
if [ $? == 0 ] ; then
logger "Ping test OK after restoring old software..."
exit 0
fi
done
logger "Ping test FAIL after restoring software, manual intervention required"
exit 2
启动定时访问功能
如果您需要将某些设备的网络访问限制在特定的每日时间范围内,请配置“mactime”插件。将其添加到/etc/vpp/startup.conf中已启用插件的列表中,然后在NAT“内部”接口上启用该功能:
代码语言:javascript复制bin mactime_enable_disable GigabitEthernet0/14/0
bin mactime_enable_disable GigabitEthernet0/14/1
...
代码语言:javascript复制
创建所需的src-mac地址规则数据库。有4种规则类型:
- allow-static - pass traffic from this mac address
- drop-static - drop traffic from this mac address
- allow-range - pass traffic from this mac address at specific times
- drop-range - drop traffic from this mac address at specific times
举例:
代码语言:javascript复制bin mactime_add_del_range name alarm-system mac 00:de:ad:be:ef:00 allow-static
bin mactime_add_del_range name unwelcome mac 00:de:ad:be:ef:01 drop-static
bin mactime_add_del_range name not-during-business-hours mac <mac> drop-range Mon - Fri 7:59 - 18:01
bin mactime_add_del_range name monday-busines-hours mac <mac> allow-range Mon 7:59 - 18:01