现在越来越多中小企业开始抛弃传统的Access VPN方案,转而向员工提供应用层代理服务器来访问内部资源。四层代理服务器方案具有部署简单、维护成本低、对BYOD设备侵入性低等特点,在不需要过多访问控制和日志记录能力,缺乏专业IT人员的情况下是一个不错的内网访问方案。但是这种方案有一个显而易见的缺点:应用层代理服务器需要应用支持。对于不支持设置代理服务器的应用,它就无能为力。另外,有些场合,比如给设备安装系统时,你并不总能找到代理服务器设置的位置。这就给应用层代理服务器的推广带来了很大麻烦。
为了克服这个缺点,我们有一个办法:在局域网设置一个透明代理网关。透明代理网关是一种应用层单臂路由,它对局域网设备来说是一个路由器,但是其特定应用层协议的上联链路是一个代理服务器。如果代理服务器支持,使用Linux内核iptables模块中的REDIRECT或TPROXY功能可以很容易地配置这样一个透明代理网关。但是一旦我们把整个局域网的默认网关配置成透明代理网关,整个局域网的流量都会经过公司的内部网络,这不一定是我们想要的结果,也不便做访问控制。另外,如果把代理网关和用户设备放在同一个二层中,用户只需要改一下设备自己的网络配置就可以使用该代理服务器,这可能导致严重的安全问题。因此,我们需要一种方法来动态地控制某台设备的默认网关是本站点的互联网出口,还是公司的代理服务器出口。
而BGP协议,正是能实现这一功能的成本最低的方案。
网络环境
- 互联网网关:运行IOS XE 16.9的Cisco ISR路由器
- 透明代理网关:运行Debian 10系统的虚拟机
网络拓扑图
部署流程
路由器
基线配置
PPPoE拨号,NAT,以及内网访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
interface GigabitEthernet0/0/0 description WAN no ip address pppoe enable group global pppoe-client dial-pool-number 1 end ! interface GigabitEthernet0/1/0 description trunk switchport mode trunk end ! interface Vlan100 description to L3 switch ip address 192.168.1.1 255.255.255.0 ip nat inside end ! interface Vlan200 description to transparent proxy ip address 192.168.2.1 255.255.255.0 ip nat inside end ! interface Dialer0 ip address negotiated ip nat outside encapsulation ppp ip tcp adjust-mss 1452 dialer pool 1 dialer-group 1 ppp authentication pap callin ppp pap sent-username xxxx password yyyy ! ip route 0.0.0.0 0.0.0.0 Dialer0 ! ip nat inside source route-map nat-wan-pppoe interface Dialer0 overload ! ip access-list standard nat-inside-ip permit 192.168.1.0 0.0.0.255 permit 192.168.2.0 0.0.0.255 permit 192.168.3.0 0.0.0.255 ! dialer-list 1 protocol ip permit ! route-map nat-wan-pppoe permit 10 match ip address nat-inside-ip match interface Dialer0 |
配置BGP Peer
为了方便起见,我们接下来要把BGP控制器也放在透明代理网关VM上,因此这里我们很简单地和透明代理网关起一个iBGP会话。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
router bgp 65001 bgp log-neighbor-changes neighbor 192.168.2.2 remote-as 65001 neighbor 192.168.2.2 description BGP Flowspec controller ! address-family ipv4 no neighbor 192.168.2.2 activate exit-address-family ! address-family ipv4 flowspec neighbor 192.168.2.2 activate neighbor 192.168.2.2 soft-reconfiguration inbound exit-address-family ! |
配置VRF
我们新建一个VRF,准备把需要走透明代理网关的流量放进来。这个VRF需要连通LAN和透明代理网关所在的二层,所以我们直接在相关的interface上设置receive,把connected路由放进VRF,再加一条默认路由去透明代理网关:
1 2 3 4 5 6 7 8 9 10 11 12 |
ip vrf PROXY description transparent proxy rd 100:100 route-target import 100:100 route-target export 100:100 interface Vlan100 ip vrf select source ip vrf receive PROXY interface Vlan200 ip vrf select source ip vrf receive PROXY ip route vrf PROXY 0.0.0.0 0.0.0.0 192.168.2.2 |
这样,所有进了这个VRF的流量就会被引导去透明代理网关。
启动Flowspec
全局启动flowspec配置安装到接口的功能即可。
1 2 3 4 |
flowspec local-install interface-all interface Vlan200 ip flowspec disable |
这里需要注意一点的是,一般应用层代理是没法处理所有类型的包的,比如ICMP这类包,如果代理服务器程序没有处理,网关上又开了转发功能,那么这些包就会被网关转发到其默认路由的next hop上,也就是我们的IOS XE路由器上。这时候,这些包又会重新被flowspec规则match一次,从而造成环路。所以我们要在从透明代理网关到路由器的端口上禁止安装flowspec规则,这些包就会和没有设置代理规则一样直接从当前site的互联网出口出去。
透明代理网关
配置透明代理
透明代理的配置不是本文重点,之前的文章里有讲过,不再赘述。
启用IP转发
这一步不是必需的,视你的配置而定。如果你希望那些没有被代理程序处理的包仍然走原来的互联网出口出去,那么就需要启用IP转发。
1 2 3 4 5 |
cat > /etc/sysctl.d/80-router.conf <<-EOF net.ipv4.ip_forward = 1 net.ipv6.conf.all.forwarding = 1 EOF sysctl -p /etc/sysctl.d/80-router.conf |
配置BGP Daemon
鉴于Bird 2的BGP flowspec语法实在是有点难受,OpenDaylight又吃内存又难用,开源的支持BGP Flowspec的BGP daemon也就剩下ExaBGP和GoBGP两个了。ExaBGP文档实在太少,这里用GoBGP为例。值得注意的是,BGP Flowspec支持设置next hop地址,但是GoBGP不知道为什么不支持这个action clause,所以我们这边用VRF方式来设置默认路由,这样配置比较复杂,但是功能相对较多。
GoBGP没有打好的Debian包,需要手工安装一下。安装流程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
wget https://github.com/osrg/gobgp/releases/download/v2.7.0/gobgp_2.7.0_linux_amd64.tar.gz tar -xvf gobgp_2.7.0_linux_amd64.tar.gz mv gobgp{,d} /usr/local/bin/ cat > /etc/systemd/system/gobgp.service <<-EOF [Unit] Description=GoBGP daemon After=network-online.target [Service] ExecStart=/usr/local/bin/gobgpd -f /etc/gobgp/gobgpd.toml [Install] Alias=gobgpd.service WantedBy=multi-user.target EOF mkdir -p /etc/gobgp touch /etc/gobgp/gobgpd.toml |
配置Peer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# /etc/gobgp/gobgpd.toml [global.config] as = 65001 router-id = "192.168.2.2" [[neighbors]] [neighbors.config] neighbor-address = "192.168.2.1" peer-as = 65001 [[neighbors.afi-safis]] [neighbors.afi-safis.config] afi-safi-name = "ipv4-flowspec" [neighbors.apply-policy.config] default-import-policy = "reject-route" default-export-policy = "accept-route" |
启动GoBGP daemon:
1 |
systemctl enable --now gobgp |
来检查一下配置是否正确,BGP会话是否已经成功建立:
1 2 3 |
root@debian:~# gobgp neighbor Peer AS Up/Down State |#Received Accepted 192.168.2.1 65001 00:01:05 Establ | 0 0 |
设置代理规则
配置好了以后,要给内网的每台设备单独设置是否走代理就很简单了。比如我们要让192.168.3.2这台机子走个代理:
1 |
gobgp global rib -a ipv4-flowspec add match source 192.168.3.2 then redirect 100:100 |
不走代理:
1 |
gobgp global rib -a ipv4-flowspec del match source 192.168.3.2 then redirect 100:100 |
甚至还能做五元组匹配和一些简单的L7匹配来实现细粒度的控制:
1 |
gobgp global rib -a ipv4-flowspec add match source 100.97.2.25 protocol tcp port 80 then redirect 100:100 |
验证配置
在网关上查看一下flowspec路由:
1 2 3 |
root@debian:~$ gobgp global rib -a ipv4-flowspec Network Next Hop AS_PATH Age Attrs *> [source: 192.168.3.2/32] fictitious 01:05:13 [{Origin: ?} {Extcomms: [redirect: 100:100]}] |
在路由器上显示flowspec配置:
1 2 3 4 |
Router#show flowspec afi-all AFI: IPv4 Flow :Source:192.168.3.2/32 Actions :Redirect: VRF PROXY Route-target: ASN2-100:100 (bgp.1) |
(如果这里显示Inactive,是因为VRF里面route-target import/export没有配置。)
现在试试在终端设备上访问一下公司内网吧。
透明代理(4核/1G内存)资源占用情况:
1 2 3 4 |
root@debian:~$ free -wh total used free shared buffers cache available Mem: 878Mi 270Mi 331Mi 4.0Mi 15Mi 261Mi 466Mi Swap: 1.0Gi 4.0Mi 1.0Gi |
附录:设置路由表
用BGP Flowspec设置VRF相比于设置next hop的好处在于,VRF是一整个路由表,而next hop是写死的一条路由。所以如果你想在某个设备走代理服务器的同时,某一段内网访问仍然走原来的出口或者另一个隧道,可以把全局路由表导入VRF。
参考: