Skip to content

Commit

Permalink
install route/arp, conflict check, custom mac_prefix, random uid
Browse files Browse the repository at this point in the history
  • Loading branch information
KusakabeShi committed Jul 30, 2021
1 parent b8c2ff3 commit 4e5c82a
Show file tree
Hide file tree
Showing 8 changed files with 840 additions and 144 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
wireguard-go
wireguard-go-vpp
vendor/*
go.sum
12 changes: 7 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@ generate-version-and-build:
[ "$$(cat version.go 2>/dev/null)" != "$$ver" ] && \
echo "$$ver" > version.go && \
git update-index --assume-unchanged version.go || true
@$(MAKE) wireguard-go
@$(MAKE) wireguard-go-vpp

wireguard-go: $(wildcard *.go) $(wildcard */*.go)
wireguard-go-vpp: $(wildcard *.go) $(wildcard */*.go)
go mod vendor && \
patch -p0 -i govpp_remove_crcstring_check.patch && \
go build -v -o "$@"

install: wireguard-go
@install -v -d "$(DESTDIR)$(BINDIR)" && install -v -m 0755 "$<" "$(DESTDIR)$(BINDIR)/wireguard-go"
install: wireguard-go-vpp
@install -v -d "$(DESTDIR)$(BINDIR)" && install -v -m 0755 "$<" "$(DESTDIR)$(BINDIR)/wireguard-go-vpp"

test:
go test -v ./...

clean:
rm -f wireguard-go
rm -f wireguard-go-vpp

.PHONY: all clean test install generate-version-and-build
176 changes: 144 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,54 +21,166 @@ This is an implementation of WireGuard in Go, but connect to vpp by libmemif ins

## Usage

You have to setup vpp first. Start VPP and run following command in vppcli
### Setup VPP
You have to setup vpp before use the wireguard-go-vpp.
Start VPP and run following command in `vppcli`

if you want to run it in pure userspace, remember to set dpdk config to `"no-pci no-hugetlb"`
if you want to run it in userspace without any kernel feature, remember to set dpdk config to `"no-pci no-hugetlb"`

Remember to replace the IP Range/MacAddr/BridgeID/InstanceID to what you want
Remember to replace the `MAC address` / `Bridge ID` /`Instance ID` to what you want. In this case,

Instance ID=42
VPPBridge ID=4242
MacAddr=42:42:42:42:42:42
MTU=1500

In this case, InstanceID=42 / BridgeID=4242 / MacAddr=42:42:42:42:42:42
```
loop create mac 42:42:42:42:42:42 instance 42
create loopback interface mac 42:42:42:42:42:42 instance 42
set int l2 bridge loop42 4242 bvi
set interface mtu 1500 loop42
set int state loop42 up
```

Setup your `IPv4` , `IPv6` and `IPv6 link-local` to interface `loop42`
```
set interface ip address loop42 10.127.111.1/8
set interface ip address loop42 fd10:127:e00f::1/10
set interface ip address loop42 fe80::aa:1111:1/128
```
Add custom route(Optional, but required on DN42 network)
```
ip route add 172.20.0.0/14 via 0.0.0.0 loop42
ip route add 172.31.0.0/16 via 0.0.0.0 loop42
```

set interface ip address loop42 192.168.37.1/24
set interface ip address loop42 fd42:4242:4242::1/10
These command above will create a interface named `loop42` with interface index `1`, you cam check it by this.
```
DBGvpp# show interface
Name Idx State MTU (L3/IP4/IP6/MPLS) Counter Count
local0 0 down 0/0/0/0
loop42 1 up 1500/0/0/0 tx packets 12
tx bytes 1160
drops 5
```
The name `loop42` and index `1` may be varied.
You need to configure it to variable `VppBridgeLoop_SwIfName` and `VppBridgeLoop_SwIfIndex` in the following section.

Similar to original wireguard-go, but you have to configure some config for the memif.
### Interface Config

Create a json file in `/etc/wggo-vpp/wg0.json` with following content:
Similar to original wireguard-go, but you have to setup some extra config for the vpp-memif and layer2/layer3 conversion.

```
All config should put in `/etc/wggo-vp` (Changeable by environment variable `VPP_MEMIF_CONFIG_DIR`)

There are two config you need to setup, First config ```if.[name].json``` is a per-interface config.

In this case, I use `home` as the interface name. Change it to whatever you like.

Create a json file at `/etc/wggo-vpp/if.home.json` with following content:

```json
{
"uid": 3,
"secret": "pwd",
"GatewayMacAddr": "42:42:42:42:42:42",
"IPv4ArpResponseRanges": [ "192.168.37.128/30" ],
"IPv4ArpLearningRanges": [ "192.168.37.0/24" ],
"IPv6NdpNeighAdvRanges": [ "fd42::/64" ],
"IPv6NdpLearningRanges": [ "fd42::/64" ],
"VppBridgeID": 4242
"uid": 3,
"secret": "some_secret",
"IPv4ArpResponseRanges": [
"172.22.77.33/32"
],
"IPv6NdpNeighAdvRanges": [
"fd28:cb8f:4c92::33/128","fe80::42:1817:1/128"
],
"IPv4ArpLearningRanges": [ ],
"IPv6NdpLearningRanges": [ ],
"VppBridgeID": 4242
}
```

### parameters
#### parameters
1. uid: Unique ID for vpp interface id, must be unique in the vpp runtime.
2. secret: the secret for the connection between vpp and wggo-vpp
3. IPv4ArpResponseRanges: While DstIP in this range, it will reply the ARP if an ARP request packet received.
4. IPv6NdpNeighAdvRanges: Similar to `IPv4ArpResponseRanges`, but it replies Neighbor Advertisement if a Neighbor Solicitation received.
5. GatewayMacAddr: The mac address of the gateway. If the dstIP out of the learning range defined below, it will use this Mac address as DstMacAddr in the vpp side.
6. IPv4ArpLearningRanges(Optional): Any dstIP within this range, wggo-vpp will lookup it's the MacAddr in the ARP table to fill the layer 2 part. If the lookup failed, it will send an ARP request and drop the original packet.
7. IPv6NdpLearningRanges(Optional): Same as `IPv4ArpLearningRanges`, but IPv6 version
3. IPv4ArpResponseRanges:
1. For `vpp -> wg` traffic within these ranges, it will reply an ARPReply if an ARP request packet received.
2. Basically it's equal to announce **I have these IPs** in the LAN.
3. Make sure **do not overlap** any IP at vpp side(like other wggo-vpp connect to same vpp bridge) otherwise it will cause IP conflict.
4. IPv4ArpLearningRanges(Optional):
1. For `vpp -> wg` traffic within these ranges, it will learn it's Mac Address to ARP table if an ARPReply packet received
2. For `wg -> vpp` traffic within these ranges, wggo-vpp will lookup the MacAddr from ARP table instead of using `GateWayMacAddr` to fill the layer2 ethernet header.
3. If the lookup failed, it will send an ARP request and drop the original packet.
5. IPv6NdpNeighAdvRanges: Similar to `IPv4ArpResponseRanges`, but it replies Neighbor Advertisement if a Neighbor Solicitation received.
1. If you add link-local address in this section, mask length must be `128` because VPP doesn't support ipv6 link-local with mask other than `/128`.
2. You can add multiple `/128` link-local address in this section if you need.
6. IPv6NdpLearningRanges(Optional): Same as `IPv4ArpLearningRanges`, but it's IPv6 version.
7. VppBridgeID: VppBridge ID defined in previous section. We need to use this value in next section.

### Gateway config

Second config ```gw.[VppBridgeID].json``` is a the config shared among all interface using the same VppBridgeID.

Create a json file at `/etc/wggo-vpp/gw.4242.json` with following content:
```
{
"GatewayMacAddr":"42:42:42:42:42:42",
"WgIfMacaddrPrefix":"98:D2:93",
"VppIfMacaddrPrefix":"A4:77:33",
"VppBridgeLoop_InstallMethod":"api",
"VppBridgeLoop_CheckRouteConflict":true,
"VppBridgeLoop_CheckRouteConfigPaths":[
"/etc/wggo-vpp"
],
"VppBridgeLoop_VppctlBin":"vppctl",
"VppBridgeLoop_SwIfName":"loop42",
"VppBridgeLoop_SwIfIndex":1,
"VppBridgeLoop_InstallNeighbor":{
"IPv4":false,
"IPv6":false,
"IPv6 link-local":false
},
"VppBridgeLoop_InstallNeighbor_Flag":{
"static":true,
"no-fib-entry":false
},
"VppBridgeLoop_InstallRoutes":{
"IPv4":true,
"IPv6":false,
"IPv6 link-local":true
}
}
```
#### parameters
1. GatewayMacAddr: The MAC address of vpp bvi interface
2. WgIfMacaddrPrefix:
1. The MAC address prefix of the interface of wggo-vpp.
2. The MAC address will be `[prefix]:[uid]`.
3. Must be unique in the whole LAN (multiple VPP or bridging to another interface).
3. VppIfMacaddrPrefix:
1. The MAC address prefix of the interface of wggo-vpp at VPP side.
2. Because this interface is bridged to VppBridgeID at vpp side, so it's useless but I think it's still better to be unique at the LAN.
4. VppBridgeLoop_CheckRouteConflict: It will read all configs to check whether there an overlap between the starting interface and other configs before interface startup. If there any overlap in `IPv4ArpResponseRanges` / `IPv6NdpNeighAdvRanges`, it will abort to start.
5. VppBridgeLoop_CheckRouteConfigPaths: All files(recursively) named with `if.*.json` in this folder will add to the checklist mentioned above.
6. VppBridgeLoop_InstallMethod: Indicate `wggo-vpp` how to install route table or arp-table to vpp.
1. `none`: disable features below completely.
2. `api`: use APIs from govpp to interact with vpp
3. `vppctl`: use external command by `exec.Command()` to interact with vpp
7. VppBridgeLoop_VppctlBin: Binary name/path of `vppctl`, default: `vppctl`
8. VppBridgeLoop_SwIfName: Interface name of the BVI interface. Required if InstallMode=`vppctl`
9. VppBridgeLoop_SwIfIndex: Interface index og the BVI interface. Required if InstallMode = `api`.
1. If it were set to `0`, it will lookup it automatically by `vppctl` with command `vppctl show interface [name]`
2. **I have no idea how to use APIs from govpp to lookup the index by name**, so I use vppctl to retrieve interface index from VPP. If **anyone knows how to do it, please contact me** or submit it in issue, thanks.
10. VppBridgeLoop_InstallNeighbor: It will install the arp entry to VPP via `api` or `vppctl` when ARPReply send to VPP.
1. Add ARP entry in VPP also add a /32 or /128 route implicitly.
2. Which is required in VPP to make IP reachable in custom routes not covered by IP/subnet of any interface.
3. You may don't need this if you use `VppBridgeLoop_InstallRoutes`, but it's safe to use both.
11. VppBridgeLoop_InstallNeighbor_Flag: The flag for the ARP entry in VPP.
12. VppBridgeLoop_InstallRoutes: Install all subnets from `IPv4ArpResponseRanges` and `IPv6NdpNeighAdvRanges` to VPP route table.
1. For custom routes not covered by IP/subnet of any interface, nexthop IP is required.
2. Any `/32(IPv4)` and `/128(IPv6)` routes adds nexthop implicitly, so our custom routes installed in `Setup VPP` section will not work property until we use this feature.
3. So I add this feature, install required `/32(IPv4)` and `/128(IPv6)` routes at startup.
4. You may don't need this if you use `VppBridgeLoop_InstallNeighbor`, but it's safe to use both.
5. Only `/32(IPv4)` and `/128(IPv6)` routes will be installed, you can remove this check by modify my source code. But I didn't check if it works.


While the JSON configured, you can run wireguard-go-vpp via following command:

```
$ wireguard-go wg0
$ wireguard-go-vpp home
```

This will create an memif in the vpp and fork into the background.
Expand All @@ -77,10 +189,10 @@ To connect to peers, just like original wireguard-go, use wireguard-tool but use

Remember to replace the path to real path
```
export WG_QUICK_USERSPACE_IMPLEMENTATION=$HOME/wireguard-go-vpp/wireguard-go
wg setconf wg0 /etc/wireguard/wg0.conf
export WG_QUICK_USERSPACE_IMPLEMENTATION=$HOME/wireguard-go-vpp/wireguard-go-vpp
wg setconf home /etc/wireguard/home.conf
```
Root permission is not required but you need the read/write access at `/run/vpp/api/api.sock`, `/var/run/vpp-memif-wg` and `/etc/wggo-vpp`. Or you can change the path by environment variables.
**Root permission is not required** but you need the read/write access at `/run/vpp/api/api.sock`, `/var/run/vpp-memif-wg` and `/etc/wggo-vpp`. Or you can change the path by environment variables.

`wg-quick` are not supported now.

Expand All @@ -89,12 +201,12 @@ It will automatically remove the interface while closing. To remove the interfac
delete interface memif memif3/3
delete memif socket id 3
```
You may instead remove the control socket via `rm -f /var/run/wireguard/wg0.sock`, which will result in wireguard-go shutting down.
You may instead remove the control socket via `rm -f /var/run/wireguard/home.sock`, which will result in wireguard-go-vpp shutting down.

To run wireguard-go without forking to the background, pass `-f` or `--foreground`:
To run wireguard-go-vpp without forking to the background, pass `-f` or `--foreground`:

```
$ wireguard-go -f wg0
$ wireguard-go-vpp -f home
```

When an interface is running, you may use [`wg(8)`](https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8) to configure it.
Expand Down
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ module golang.zx2c4.com/wireguard
go 1.16

require (
git.fd.io/govpp.git v0.3.6-0.20210601140839-da95997338b7
git.fd.io/govpp.git/extras v0.0.0-20210601140839-da95997338b7
git.fd.io/govpp.git v0.3.6-0.20210727130229-24f179dbb953
git.fd.io/govpp.git/extras v0.0.0-20210727130229-24f179dbb953
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/google/gopacket v1.1.19
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect
github.com/sirupsen/logrus v1.8.1
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
Expand Down
22 changes: 0 additions & 22 deletions go.sum

This file was deleted.

File renamed without changes.
20 changes: 20 additions & 0 deletions govpp_remove_crcstring_check.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--- vendor/git.fd.io/govpp.git/adapter/socketclient/socketclient.go 2021-07-29 22:21:35.560204223 +0800
+++ vendor/git.fd.io/govpp.git/adapter/socketclient/socketclient.go 2021-07-30 04:53:13.528822544 +0800
@@ -314,6 +314,8 @@
for _, x := range reply.MessageTable {
msgName := strings.Split(x.Name, "\x00")[0]
name := strings.TrimSuffix(msgName, "\x13")
+ nameslice := strings.Split(name, "_")
+ name = strings.Join(nameslice[:len(nameslice)-1], "_")
c.msgTable[name] = x.Index
if strings.HasPrefix(name, "sockclnt_delete_") {
c.sockDelMsgId = x.Index
@@ -327,7 +329,7 @@
}

func (c *Client) GetMsgID(msgName string, msgCrc string) (uint16, error) {
- if msgID, ok := c.msgTable[msgName+"_"+msgCrc]; ok {
+ if msgID, ok := c.msgTable[msgName]; ok {
return msgID, nil
}
return 0, &adapter.UnknownMsgError{
Loading

0 comments on commit 4e5c82a

Please sign in to comment.