zl程序教程

您现在的位置是:首页 >  其他

当前栏目

learning:Wireguard plugin

2023-02-19 12:21:05 时间

本文主要介绍wireguard的vpp的基本配置与转发流程,其他相关wireguard原理及理论实现可以阅读参考文章。

简介

wireguard插件是VPP的wireguard协议的实现。它允许创建安全的V**隧道。基于wireguard-openbsd的实现的。最初是在vpp的20.09版本加入的,但是后期又做了很多的优化,本文测试环境基于21.10release版本。下面是vpp代码中特性描述。

name: Wireguard protocol
maintainer: Artem Glazychev <artem.glazychev@xored.com>
features:
  - "based on wireguard-openbsd implementation: https://git.zx2c4.com/wireguard-openbsd"
  - creating secure VPN-tunnel
description: "Wireguard protocol implementation"
state: development#说明目前还是开发阶段
properties: [API, CLI]
missing:
  - IPv6 support#不支持ipv6
  - DoS protection as in the original protocol#不支持原始协议中的DoS保护

wireguard插件状态还是开发阶段,在测试过程中也发现目前只支持端到端直接连接:这是最简单的拓扑,所有的节点要么在同一个局域网,要么直接通过公网访问,这样 WireGuard 可以直接连接到对端,不需要中继跳转。 其他场景比如一端出于nat设备后面,一端是公网的拓扑,可能需要修改代码,目前测试情况公网测也需要明确指定对端ip地址。

配置与测试

组网图如下所示:在vpp1上ping 114.114.114.114可以ping通,实现基于wireguard v**功能:

learning vpp1配置如下:

set interface state GigabitEthernet2/2/0 up
set interface ip address GigabitEthernet2/2/0 192.168.100.1/24
#创建wireguard接口并设置ip地址。
wireguard create port 1000 src 192.168.100.1 generate-key
set interface state wg0 up
set interface ip address wg0 100.1.1.1/24
#设置对端key及allowed-ip信息。
wireguard peer add wg0 public-key niRroULUniHipM0oNC4VvzKeG2gGvFTQIKe06B7/tDA= endpoint 192.168.100.2 port 3000 allowed-ip 100.1.1.0/24 allowed-ip 114.114.114.114/32 persistent-keepalive 1

learning vpp2 配置

#设置dhcp client
set interface state GigabitEthernet2/4/0 up
set dhcp client intfc GigabitEthernet2/4/0
#配置nat
nat44 enable
nat44 add interface address GigabitEthernet2/4/0
set interface nat44 out GigabitEthernet2/4/0 output-feature

set interface state GigabitEthernet2/2/0 up
set interface ip address GigabitEthernet2/2/0 192.168.100.2/24
#创建wireguard接口并动态生成私有和共有key
wireguard create listen-port 3000  src 192.168.100.2 generate-key
set interface state wg0 up
set interface ip address wg0 100.1.1.2/24
设置对端wireguard peer信息
wireguard peer add wg0 public-key ypHUhsyCetXypKImMGpl7dxhDGOAhaMKa3iwS3TB6Cc= endpoint 192.168.100.1 port 1000 allowed-ip 100.1.1.0/24 persistent-keepalive 1

在vpp1上ping 114.114.114.114 在vpp2上trace流程如下:

#ping请求报文
22:37:51:464540: dpdk-input
  GigabitEthernet2/2/0 rx queue 0
  buffer 0x920eb: current data 0, length 170, buffer-pool 0, ref-count 1, totlen-nifb 0, trace handle 0x1
                  ext-hdr-valid 
                  l4-cksum-computed l4-cksum-correct 
  PKT MBUF: port 0, nb_segs 1, pkt_len 170
    buf_len 2176, data_len 170, ol_flags 0x8, data_off 128, phys_addr 0x14e83b40
    packet_type 0x0 l2_len 0 l3_len 0 outer_l2_len 0 outer_l3_len 0 
    rss 0x0 fdir.hi 0x0 fdir.lo 0x0
    Packet Offload Flags
      PKT_RX_L4_CKSUM_BAD (0x0008) L4 cksum of RX pkt. is not OK
  IP4: 00:0c:29:a2:43:e1 -> 00:0c:29:07:6f:a4
  UDP: 192.168.100.1 -> 192.168.100.2
    tos 0x00, ttl 63, length 156, checksum 0x31fd dscp CS0 ecn NON_ECN
    fragment id 0x0000
  UDP: 1000 -> 3000
    length 136, checksum 0x0000
22:37:51:464604: ethernet-input
  frame: flags 0x3, hw-if-index 1, sw-if-index 1
  IP4: 00:0c:29:a2:43:e1 -> 00:0c:29:07:6f:a4
22:37:51:464639: ip4-input-no-checksum
  UDP: 192.168.100.1 -> 192.168.100.2
    tos 0x00, ttl 63, length 156, checksum 0x31fd dscp CS0 ecn NON_ECN
    fragment id 0x0000
  UDP: 1000 -> 3000
    length 136, checksum 0x0000
22:37:51:464666: ip4-lookup
  fib 0 dpo-idx 7 flow hash: 0x00000000
  UDP: 192.168.100.1 -> 192.168.100.2
    tos 0x00, ttl 63, length 156, checksum 0x31fd dscp CS0 ecn NON_ECN
    fragment id 0x0000
  UDP: 1000 -> 3000
    length 136, checksum 0x0000
22:37:51:464695: ip4-local
    UDP: 192.168.100.1 -> 192.168.100.2
      tos 0x00, ttl 63, length 156, checksum 0x31fd dscp CS0 ecn NON_ECN
      fragment id 0x0000
    UDP: 1000 -> 3000
      length 136, checksum 0x0000
22:37:51:464717: ip4-udp-lookup
  UDP: src-port 1000 dst-port 3000
22:37:51:464736: wg-input
  WG input: 
  Type: Data
  peer: 0
  Length: 96
  Keepalive: false
22:37:51:464801: ip4-input-no-checksum
  ICMP: 100.1.1.1 -> 114.114.114.114
    tos 0x00, ttl 254, length 96, checksum 0x72b6 dscp CS0 ecn NON_ECN
    fragment id 0x0000
  ICMP echo_request checksum 0x729e id 19596
22:37:51:464831: ip4-lookup
  fib 0 dpo-idx 21 flow hash: 0x00000000
  ICMP: 100.1.1.1 -> 114.114.114.114
    tos 0x00, ttl 254, length 96, checksum 0x72b6 dscp CS0 ecn NON_ECN
    fragment id 0x0000
  ICMP echo_request checksum 0x729e id 19596
22:37:51:464857: ip4-load-balance
  fib 0 dpo-idx 8 flow hash: 0x00000000
  ICMP: 100.1.1.1 -> 114.114.114.114
    tos 0x00, ttl 254, length 96, checksum 0x72b6 dscp CS0 ecn NON_ECN
    fragment id 0x0000
  ICMP echo_request checksum 0x729e id 19596
22:37:51:464884: ip4-rewrite
  tx_sw_if_index 3 dpo-idx 8 : ipv4 via 192.168.1.1 GigabitEthernet2/4/0: mtu:9000 next:7 flags:[features ] 446a2ebdb5be000c29076fb8080
0 flow hash: 0x00000000
  00000000: 446a2ebdb5be000c29076fb808004500006000000000fd0173b6640101017272
  00000020: 72720800729e4c8c01dc4543777910b5000000010203040506070809
22:37:51:464916: ip4-sv-reassembly-output-feature
  [not-fragmented]
22:37:51:464944: nat-pre-in2out-output
  in2out next_index 4 arc_next_index 11
22:37:51:464972: nat44-ed-in2out-output
  NAT44_IN2OUT_ED_FAST_PATH: sw_if_index 4, next index 11, session 0, translation result 'success' via i2of
  i2of match: saddr 100.1.1.1 sport 19596 daddr 114.114.114.114 dport 19596 proto ICMP fib_idx 0 rewrite: saddr 192.168.1.82 daddr 114.
114.114.114 icmp-id 19596 txfib 0 
  o2if match: saddr 114.114.114.114 sport 19596 daddr 192.168.1.82 dport 19596 proto ICMP fib_idx 0 rewrite: daddr 100.1.1.1 icmp-id 19
596 txfib 0 
  search key local 100.1.1.1:19596 remote 114.114.114.114:19596 proto ICMP fib 0 thread-index 32767 session-index 4159750904
22:37:51:465059: GigabitEthernet2/4/0-output
  GigabitEthernet2/4/0 
  IP4: 00:0c:29:07:6f:b8 -> 44:6a:2e:bd:b5:be
  ICMP: 192.168.1.82 -> 114.114.114.114
    tos 0x00, ttl 253, length 96, checksum 0x16be dscp CS0 ecn NON_ECN
    fragment id 0x0000
  ICMP echo_request checksum 0x729e id 19596
22:37:51:465087: GigabitEthernet2/4/0-tx
  GigabitEthernet2/4/0 tx queue 0
  buffer 0x920eb: current data 28, length 110, buffer-pool 0, ref-count 1, totlen-nifb 0, trace handle 0x1
                  ext-hdr-valid 
                  l4-cksum-computed l4-cksum-correct natted l2-hdr-offset 0 l3-hdr-offset 14 
  PKT MBUF: port 0, nb_segs 1, pkt_len 110
    buf_len 2176, data_len 110, ol_flags 0x8, data_off 156, phys_addr 0x14e83b40
    packet_type 0x0 l2_len 0 l3_len 0 outer_l2_len 0 outer_l3_len 0 
    rss 0x0 fdir.hi 0x0 fdir.lo 0x0
    Packet Offload Flags
      PKT_RX_L4_CKSUM_BAD (0x0008) L4 cksum of RX pkt. is not OK
  IP4: 00:0c:29:07:6f:b8 -> 44:6a:2e:bd:b5:be
  ICMP: 192.168.1.82 -> 114.114.114.114
    tos 0x00, ttl 253, length 96, checksum 0x16be dscp CS0 ecn NON_ECN
    fragment id 0x0000
  ICMP echo_request checksum 0x729e id 19596
#ping回应报文
22:37:51:491888: dpdk-input
  GigabitEthernet2/4/0 rx queue 0
  buffer 0x7c41c: current data 0, length 110, buffer-pool 0, ref-count 1, totlen-nifb 0, trace handle 0x2
                  ext-hdr-valid 
                  l4-cksum-computed l4-cksum-correct 
  PKT MBUF: port 2, nb_segs 1, pkt_len 110
    buf_len 2176, data_len 110, ol_flags 0x0, data_off 128, phys_addr 0x14510780
    packet_type 0x0 l2_len 0 l3_len 0 outer_l2_len 0 outer_l3_len 0 
    rss 0x0 fdir.hi 0x0 fdir.lo 0x0
  IP4: 44:6a:2e:bd:b5:be -> 00:0c:29:07:6f:b8
  ICMP: 114.114.114.114 -> 192.168.1.82
    tos 0x04, ttl 91, length 96, checksum 0xd287 dscp unknown ecn NON_ECN
    fragment id 0xe632
  ICMP echo_reply checksum 0x7a9e id 19596
22:37:51:491957: ethernet-input
  frame: flags 0x3, hw-if-index 3, sw-if-index 3
  IP4: 44:6a:2e:bd:b5:be -> 00:0c:29:07:6f:b8
22:37:51:491993: ip4-input-no-checksum
  ICMP: 114.114.114.114 -> 192.168.1.82
    tos 0x04, ttl 91, length 96, checksum 0xd287 dscp unknown ecn NON_ECN
    fragment id 0xe632
  ICMP echo_reply checksum 0x7a9e id 19596
22:37:51:492016: ip4-sv-reassembly-feature
  [not-fragmented]
22:37:51:492036: nat-pre-out2in
  out2in next_index 6 arc_next_index 10
22:37:51:492054: nat44-ed-out2in
  NAT44_OUT2IN_ED_FAST_PATH: sw_if_index 3, next index 10, session 0, translation result 'success' via o2if
  i2of match: saddr 100.1.1.1 sport 19596 daddr 114.114.114.114 dport 19596 proto ICMP fib_idx 0 rewrite: saddr 192.168.1.82 daddr 114.
114.114.114 icmp-id 19596 txfib 0 
  o2if match: saddr 114.114.114.114 sport 19596 daddr 192.168.1.82 dport 19596 proto ICMP fib_idx 0 rewrite: daddr 100.1.1.1 icmp-id 19
596 txfib 0 
  search key local 114.114.114.114:19596 remote 192.168.1.82:19596 proto ICMP fib 0 thread-index 32767 session-index 2988650768
 no reason for slow path
22:37:51:492103: ip4-lookup
  fib 0 dpo-idx 2 flow hash: 0x00000000
  ICMP: 114.114.114.114 -> 100.1.1.1
    tos 0x04, ttl 91, length 96, checksum 0x2f80 dscp unknown ecn NON_ECN
    fragment id 0xe632
  ICMP echo_reply checksum 0x7a9e id 19596
22:37:51:492129: ip4-midchain
  tx_sw_if_index 4 dpo-idx 2 : ipv4 [features] via 192.168.100.1 wg0: mtu:9000 next:3 flags:[features ] 450000000000000040113199c0a8640
2c0a864010bb803e800000000
  stacked-on entry:15:
    [@3]: ipv4 via 192.168.100.1 GigabitEthernet2/2/0: mtu:9000 next:5 flags:[] 000c29a243e1000c29076fa40800 flow hash: 0x00000000
  00000000: 450000000000000040113199c0a86402c0a864010bb803e80000000045040060
  00000020: e63200005a013080727272726401010100007a9e4c8c01dc45437779
22:37:51:492152: wg-output-tun
  peer: 0
  Encrypted packet: UDP: 192.168.100.2 -> 192.168.100.1
                      tos 0x00, ttl 64, length 156, checksum 0x30fd dscp CS0 ecn NON_ECN
                      fragment id 0x0000
                    UDP: 3000 -> 1000
                      length 136, checksum 0x0000:$U
22:37:51:492227: adj-midchain-tx
  adj-midchain:[2]:ipv4 [features] via 192.168.100.1 wg0: mtu:9000 next:3 flags:[features ] 450000000000000040113199c0a86402c0a864010bb
803e800000000
  stacked-on entry:15:
    [@3]: ipv4 via 192.168.100.1 GigabitEthernet2/2/0: mtu:9000 next:5 flags:[] 000c29a243e1000c29076fa40800
22:37:51:492246: ip4-rewrite
  tx_sw_if_index 1 dpo-idx 3 : ipv4 via 192.168.100.1 GigabitEthernet2/2/0: mtu:9000 next:5 flags:[] 000c29a243e1000c29076fa40800 flow 
hash: 0x00000000
  00000000: 000c29a243e1000c29076fa408004500009c000000003f1131fdc0a86402c0a8
  00000020: 64010bb803e80088000004000000777b212f940000000000000009ba
22:37:51:492264: GigabitEthernet2/2/0-output
  GigabitEthernet2/2/0 
  IP4: 00:0c:29:07:6f:a4 -> 00:0c:29:a2:43:e1
  UDP: 192.168.100.2 -> 192.168.100.1
    tos 0x00, ttl 63, length 156, checksum 0x31fd dscp CS0 ecn NON_ECN
    fragment id 0x0000
  UDP: 3000 -> 1000
    length 136, checksum 0x0000
22:37:51:492285: GigabitEthernet2/2/0-tx
  GigabitEthernet2/2/0 tx queue 0
  buffer 0x7c41c: current data -28, length 170, buffer-pool 0, ref-count 1, totlen-nifb 0, trace handle 0x2
                  ext-hdr-valid 
                  l4-cksum-computed l4-cksum-correct l2-hdr-offset 0 l3-hdr-offset 14 
  PKT MBUF: port 2, nb_segs 1, pkt_len 170
    buf_len 2176, data_len 170, ol_flags 0x0, data_off 100, phys_addr 0x14510780
    packet_type 0x0 l2_len 0 l3_len 0 outer_l2_len 0 outer_l3_len 0 
    rss 0x0 fdir.hi 0x0 fdir.lo 0x0
  IP4: 00:0c:29:07:6f:a4 -> 00:0c:29:a2:43:e1
  UDP: 192.168.100.2 -> 192.168.100.1
    tos 0x00, ttl 63, length 156, checksum 0x31fd dscp CS0 ecn NON_ECN
    fragment id 0x0000
  UDP: 3000 -> 1000
    length 136, checksum 0x0000

wireguard解封装流程和ipsec的流程都是一样的,这里重点看一个封装流程。下面是查询路由情况,回应报文是一个路由链,直接可以查询到ipsec封装和外层路由,减少一次外层路由查询过程。对应转发流程,可以看上面trace流程中回应报文处理node流程。

DBGvpp# show ip fib 100.1.1.1 table 0
ipv4-VRF:0, fib_index:0, flow hash:[src dst sport dport proto flowlabel ] epoch:0 flags:none locks:[adjacency:1, recursive-resolution:2, default-route:1, nat-hi:2, ]
100.1.1.0/24 fib:0 index:11 locks:3
  wireguard refs:1 src-flags:added,contributing,active,
  ......
 forwarding:   unicast-ip4-chain ##wireguard 封装
  [@0]: dpo-load-balance: [proto:ip4 index:13 buckets:1 uRPF:20 to:[1890:181440] via:[14:1344]]
    [0] [@6]: ipv4 [features] via 192.168.100.1 wg0: mtu:9000 next:3 flags:[features ] 450000000000000040113199c0a86402c0a864010bb803e800000000
        stacked-on entry:15: #外层封装
          [@3]: ipv4 via 192.168.100.1 GigabitEthernet2/2/0: mtu:9000 next:5 flags:[] 000c29a243e1000c29076fa40800

其他说明

1、wireguard插件编译 wireguard插件依赖openssl1.1.0版本及以上,所以建议使用ubuntu最新的系统,另外vpp 21.10版本已经无法在Centos版本编译通过。需要升级gcc版本。vpp在邮件中也有说明后期不再维护centos版本。本文是在Ubuntu 20.04.3 LTS系统编译的。

2、当前vpp版本需要明确指定wireguard 两端endpoint ip地址。一端出于nat后面目前是无法使用的,需要修改代码。

3、vpp 和阿里云服务器wireguard对接,目前也是配置OK,转发流量未测试。

[root@jinsh ~]# wg
interface: wg0
  public key: /NIaFfvwYmI5Wdy0jsIzkCbUvAjIc2hFGJHCOUx4DVc=
  private key: (hidden)
  listening port: 51820

peer: kX90FuB+DZnKKPopjsj9ktAv9bR7dpoQPbpzBM73ezs=
  endpoint: 120.245.130.195:2703
  allowed ips: 10.0.0.2/32
  latest handshake: 1 hour, 7 seconds ago
  transfer: 1.79 MiB received, 41.78 KiB sent

巨人的肩膀

1、wireguard文档github仓库:https://github.com/pirate/wireguard-docs 2、wireguard相关的博客:https://fuckcloudnative.io/tags/wireguard/ 3、vpp文档wireguard简介

https://docs.fd.io/vpp/21.10/d5/d54/wireguard_plugin_doc.html 4、wireguard配置说明:https://www.wireguard.com/quickstart/