在家也要玩BGP(2):可控地给部分局域网设备设置透明代理网关

现在越来越多中小企业开始抛弃传统的Access VPN方案,转而向员工提供应用层代理服务器来访问内部资源。四层代理服务器方案具有部署简单、维护成本低、对BYOD设备侵入性低等特点,在不需要过多访问控制和日志记录能力,缺乏专业IT人员的情况下是一个不错的内网访问方案。但是这种方案有一个显而易见的缺点:应用层代理服务器需要应用支持。对于不支持设置代理服务器的应用,它就无能为力。另外,有些场合,比如给设备安装系统时,你并不总能找到代理服务器设置的位置。这就给应用层代理服务器的推广带来了很大麻烦。

为了克服这个缺点,我们有一个办法:在局域网设置一个透明代理网关。透明代理网关是一种应用层单臂路由,它对局域网设备来说是一个路由器,但是其特定应用层协议的上联链路是一个代理服务器。如果代理服务器支持,使用Linux内核iptables模块中的REDIRECT或TPROXY功能可以很容易地配置这样一个透明代理网关。但是一旦我们把整个局域网的默认网关配置成透明代理网关,整个局域网的流量都会经过公司的内部网络,这不一定是我们想要的结果,也不便做访问控制。另外,如果把代理网关和用户设备放在同一个二层中,用户只需要改一下设备自己的网络配置就可以使用该代理服务器,这可能导致严重的安全问题。因此,我们需要一种方法来动态地控制某台设备的默认网关是本站点的互联网出口,还是公司的代理服务器出口。

而BGP协议,正是能实现这一功能的成本最低的方案。

网络环境

  • 互联网网关:运行IOS XE 16.9的Cisco ISR路由器
  • 透明代理网关:运行Debian 10系统的虚拟机

网络拓扑图

 

部署流程

路由器

基线配置

PPPoE拨号,NAT,以及内网访问。

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会话。

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,再加一条默认路由去透明代理网关:

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配置安装到接口的功能即可。

flowspec
 local-install interface-all
interface Vlan200
 ip flowspec disable

这里需要注意一点的是,一般应用层代理是没法处理所有类型的包的,比如ICMP这类包,如果代理服务器程序没有处理,网关上又开了转发功能,那么这些包就会被网关转发到其默认路由的next hop上,也就是我们的IOS XE路由器上。这时候,这些包又会重新被flowspec规则match一次,从而造成环路。所以我们要在从透明代理网关到路由器的端口上禁止安装flowspec规则,这些包就会和没有设置代理规则一样直接从当前site的互联网出口出去。

透明代理网关

配置透明代理

透明代理的配置不是本文重点,之前的文章里有讲过,不再赘述。

启用IP转发

这一步不是必需的,视你的配置而定。如果你希望那些没有被代理程序处理的包仍然走原来的互联网出口出去,那么就需要启用IP转发。

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包,需要手工安装一下。安装流程:

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:

# /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:

systemctl enable --now gobgp

来检查一下配置是否正确,BGP会话是否已经成功建立:

[email protected]:~# gobgp neighbor
Peer           AS  Up/Down State       |#Received  Accepted
192.168.2.1 65001 00:01:05 Establ      |        0         0

设置代理规则

配置好了以后,要给内网的每台设备单独设置是否走代理就很简单了。比如我们要让192.168.3.2这台机子走个代理:

gobgp global rib -a ipv4-flowspec add match source 192.168.3.2 then redirect 100:100

不走代理:

gobgp global rib -a ipv4-flowspec del match source 192.168.3.2 then redirect 100:100

甚至还能做五元组匹配和一些简单的L7匹配来实现细粒度的控制:

gobgp global rib -a ipv4-flowspec add match source 100.97.2.25 protocol tcp port 80 then redirect 100:100

验证配置

在网关上查看一下flowspec路由:

[email protected]:~$ 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配置:

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内存)资源占用情况:

[email protected]:~$ 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


参考:

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据