25 Commits

Author SHA1 Message Date
438d80cda6 Merge branch 'dev' into release-0.2 2023-03-31 16:22:15 +02:00
6d14614043 Pass Slice by reference, not value 2023-03-31 16:22:01 +02:00
8488a9e4cd move netchecks to subfolder of wgchecks 2023-03-30 14:28:19 +02:00
0c85d8ae1a Update dependencies 2023-03-30 14:28:05 +02:00
05bab9dd60 Fix compose-example 2023-03-30 14:25:59 +02:00
36e8aa9b87 Merge branch 'feat_periodicSync' into dev 2023-03-30 12:44:40 +02:00
9a700a117c Add documentation for PERIODIC_SYNC 2023-03-30 12:44:09 +02:00
add4e8dbcf Add function to run periodic checks 2023-03-30 12:39:38 +02:00
74bc32fc2c Add env-var and check for periodic-sync 2023-03-30 12:34:18 +02:00
56b47e8fb6 Move setting all routes to own func 2023-03-30 12:31:22 +02:00
d5886fcb4a Add iproute2 as packet 2022-11-17 14:51:53 +01:00
180f11cb86 Add warning-output for errors in iproute2mapping 2022-11-17 14:51:38 +01:00
d0e6fa65d2 Fix error-reporting 2022-11-17 14:51:18 +01:00
f136bcb207 Fix wrong docker-service and image name 2022-11-15 22:49:06 +01:00
d0840e6171 Swap check for slightly better performance 2022-11-15 22:48:10 +01:00
9d31008d29 Remove unnecessary require 2022-11-15 22:47:53 +01:00
323db065ad Add information about required capabilites for docker 2022-11-15 19:25:16 +01:00
ca9507e26f Add documentation about environment-vars 2022-11-15 19:14:19 +01:00
5860e53690 Merge branch 'release-0.1' into dev 2022-11-15 18:47:43 +01:00
111d316802 Add missing \ 2022-11-15 18:47:21 +01:00
11d703efcb Add build scripts and dockerfile 2022-11-15 18:14:08 +01:00
5d40cde0c8 Add project 2022-11-15 18:12:16 +01:00
b250277bab Add documentation 2022-11-15 18:11:49 +01:00
f6c24f0eaa Change package-name 2022-11-03 08:43:40 +01:00
5aae6c456e Create go-project 2022-11-03 08:36:28 +01:00
18 changed files with 1599 additions and 1 deletions

25
Dockerfile Normal file
View File

@@ -0,0 +1,25 @@
# ---- Base ----
FROM alpine:3 AS base
WORKDIR /app
# Install necessary packages
RUN apk add --no-cache iproute2
# ---- Build ----
FROM golang:1.19-alpine AS build
WORKDIR /build
# Copy sources
ADD . .
# Get dependencies
RUN go get ./cmd/app
# Compile
RUN CGO_ENABLED=0 go build -a -o app ./cmd/app
# ---- Release ----
FROM base AS release
# Copy build-target
COPY --from=build /build/app .
CMD ["./app"]

View File

@@ -1,4 +1,95 @@
RoutingTableToWGTranslator RoutingTableToWG
-- --
Translate Routing-Table Entries to Wireguard AllowedIPs with Filters Translate Routing-Table Entries to Wireguard AllowedIPs with Filters
<br>
<!-- TOC -->
- [1. Overview](#1-overview)
- [1.1. Usage](#11-usage)
- [1.2. Install](#12-install)
- [2. Behaviour](#2-behaviour)
- [2.1. Adding Route](#21-adding-route)
- [2.2. Deleting Route](#22-deleting-route)
<!-- /TOC -->
<br>
# 1. Overview
## 1.1. Usage
The Program will listen for RoutingTable Changes and can translate the changes to a Wireguard-Interface.
It will detect the Peer to add the Route to using the Gateway from the Route-Entry.<br>
In case routes clash or cant be added to Wireguard, Warnings will be logged.
<br>
### 1.1.1. Examples
- Dynamic Routing with Routing-Protocols (e.g. OSPF)
- Interacting with Wireguard using the familiar Tools like `iproute2`
<br>
## 1.2. Install
### 1.2.1. Environment
Variable|Description|Type|Default
-|-|-|-
`INTERFACE`* | Wireguard-Interface Name | String |
`FILTER_PROTOCOL` | Protocol to react on | Number / iproute2-name | All
`FILTER_TABLE` | Table to react on | Number / iproute2-name | All
`PERIODIC_SYNC` | Reguarly sync the routing-table <br> Useful when the wg-interface is changed/updated without us knowing | Seconds | -1
*\* Required*
<br>
### 1.2.2. Docker
Depending on the needs, the Container can be run in `network_mode: host` to be able to access routing-tables and interfaces of the host.
Additionally the capability `NET_ADMIN` is required for interacting with interfaces.
<details><summary><code>docker-compose.yml</code></summary>
```yaml
version: '3'
services:
routingtabletowg:
image: ruakij/routingtabletowg
restart: unless-stopped
network_mode: host
cap_add:
- NET_ADMIN
environment:
- INTERFACE=<wgInterfaceName or empty for wg0>
```
</details>
<br>
### 1.2.3. Without Docker
Clone the Repository `git clone <URI>` and build the Program with `go build cmd/app`
Then you can run it with `./app`
<br>
# 2. Behaviour
## 2.1. Adding Route
![](doc/add-route.svg)
<br>
## 2.2. Deleting Route
![](doc/del-route.svg)

9
build/docker-multiarch.sh Executable file
View File

@@ -0,0 +1,9 @@
TAG="ruakij/routingtabletowg"
PLATFORM="linux/amd64,linux/arm64/v8,linux/arm/v7"
EXTRA_ARGS="$@"
docker buildx build \
--platform $PLATFORM \
--tag $TAG \
$EXTRA_ARGS \
.

7
build/docker-ownarch.sh Executable file
View File

@@ -0,0 +1,7 @@
TAG="ruakij/routingtabletowg"
EXTRA_ARGS="$@"
docker build \
--tag $TAG \
$EXTRA_ARGS \
.

18
cmd/app/filter.go Normal file
View File

@@ -0,0 +1,18 @@
package main
import (
"github.com/vishvananda/netlink"
)
type FilterOptions struct {
Table int
Protocol int
}
func CheckFilter(options FilterOptions, route netlink.Route) bool {
if (options.Table != -1 && options.Table != route.Table) ||
(options.Protocol != -1 && options.Protocol != route.Protocol) {
return false
}
return true
}

17
cmd/app/logger.go Normal file
View File

@@ -0,0 +1,17 @@
package main
import (
"log"
"os"
)
type Log struct {
Info log.Logger
Warn log.Logger
Error log.Logger
}
var logger Log = Log{
Info: *log.New(os.Stdout, "[INFO]\t", log.Ltime|log.Lshortfile),
Warn: *log.New(os.Stderr, "[WARN]\t", log.Ltime|log.Lshortfile),
Error: *log.New(os.Stderr, "[ERROR]\t", log.Ltime|log.Lshortfile),
}

254
cmd/app/main.go Normal file
View File

@@ -0,0 +1,254 @@
package main
import (
"net"
"os"
"strconv"
"time"
envChecks "git.ruekov.eu/ruakij/routingtabletowg/lib/environmentchecks"
ip2Map "git.ruekov.eu/ruakij/routingtabletowg/lib/iproute2mapping"
"git.ruekov.eu/ruakij/routingtabletowg/lib/wgchecks"
"github.com/vishvananda/netlink"
"golang.org/x/sys/unix"
"golang.zx2c4.com/wireguard/wgctrl"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
var envRequired = []string{
"INTERFACE",
}
var envDefaults = map[string]string{
"INTERFACE": "wg0",
//"MANAGE_ALL": "true",
"FILTER_PROTOCOL": "-1",
"FILTER_TABLE": "-1",
"PERIODIC_SYNC": "-1",
}
func main() {
// Environment-vars
err := envChecks.HandleRequired(envRequired)
if(err != nil){
logger.Error.Fatal(err)
}
envChecks.HandleDefaults(envDefaults)
iface := os.Getenv("INTERFACE")
//MANAGE_ALL = os.Getenv("MANAGE_ALL")
// Check if ip2Map has init-errors
for _, err := range ip2Map.Errors {
logger.Warn.Printf("iproute2mapping: %s", err)
}
// Parse filter-env-vars
filterProtocolStr := os.Getenv("FILTER_PROTOCOL")
filterProtocol, err := ip2Map.TryGetId(ip2Map.PROTOCOL, filterProtocolStr)
if err != nil {
logger.Error.Fatalf("Couldn't read FILTER_PROTOCOL '%s': %s", filterProtocolStr, err)
}
filterTableStr := os.Getenv("FILTER_TABLE")
filterTable, err := ip2Map.TryGetId(ip2Map.TABLE, filterTableStr)
if err != nil {
logger.Error.Fatalf("Couldn't read FILTER_TABLE '%s': %s", filterTableStr, err)
}
periodicSyncStr := os.Getenv("PERIODIC_SYNC")
periodicSync, err := strconv.Atoi(periodicSyncStr)
if err != nil {
logger.Error.Fatalf("Couldn't read PERIODIC_SYNC '%s': %s", periodicSyncStr, err)
}
// Create filter
filterOptions := FilterOptions{
Table: filterTable,
Protocol: filterProtocol,
}
// Get Link-Device
link, err := netlink.LinkByName(iface)
if err != nil {
logger.Error.Fatalf("Couldn't get interface '%s': %s", iface, err)
}
// Test getting wg-client
client, err := wgctrl.New()
if err != nil {
logger.Error.Fatalf("Couldn't create wgctl-client: %s", err)
}
// Test getting wg-device
_, err = client.Device(iface)
if err != nil {
logger.Error.Fatalf("Couldn't get wg-interface '%s': %s", iface, err)
}
// Subscribe to route-change events
routeSubChan, routeSubDoneChan := make(chan netlink.RouteUpdate), make(chan struct{})
netlink.RouteSubscribe(routeSubChan, routeSubDoneChan)
go handleRouteEvents(routeSubChan, filterOptions, iface)
//# Initial Route-setup
// Get routing-table entries from device
routeList, err := netlink.RouteList(link, netlink.FAMILY_ALL)
if err != nil {
logger.Error.Fatalf("Couldn't get route-entries: %s", err)
}
logger.Info.Printf("Initially setting all current routes")
syncCurrentRoutesToHandler(routeSubChan, routeList)
if(periodicSync > 0){
go runPeriodicSync(periodicSync, link, routeSubChan)
}
select {}
}
func runPeriodicSync(seconds int, link netlink.Link, routeSubChan chan netlink.RouteUpdate){
interval := time.Duration(seconds) * time.Second
for {
time.Sleep(interval)
// Get routing-table entries from device
routeList, err := netlink.RouteList(link, netlink.FAMILY_ALL)
if err != nil {
logger.Error.Fatalf("Couldn't get route-entries: %s", err)
}
logger.Info.Printf("Periodically syncing all routes")
syncCurrentRoutesToHandler(routeSubChan, routeList)
}
}
func syncCurrentRoutesToHandler(routeSubChan chan netlink.RouteUpdate, routeList []netlink.Route){
for _, route := range routeList {
// Ignore routes with empty gateway
if(route.Gw == nil){
continue
}
// Send current routes to handler
routeSubChan <- netlink.RouteUpdate{
Type: unix.RTM_NEWROUTE,
Route: route,
}
}
}
var routeUpdateTypeMapFromId = map[uint16]string{
unix.RTM_NEWROUTE: "+",
unix.RTM_DELROUTE: "-",
}
// TODO: Add proxy to apply filter in channels rather than.. this mess
func handleRouteEvents(routeSubChan <-chan netlink.RouteUpdate, filterOptions FilterOptions, iface string) {
// Create wg-client
client, err := wgctrl.New()
if err != nil {
logger.Error.Fatalf("Couldn't create wgctl-client: %s", err)
}
for {
// Receive Route-Updates
routeUpdate := <-routeSubChan
route := routeUpdate.Route
// Check filter
if(!CheckFilter(filterOptions, routeUpdate.Route)){
continue
}
// Special case for default-route
if route.Dst == nil{
if route.Gw.To4() != nil { // IPv4
route.Dst = &net.IPNet{
IP: net.IPv4zero,
Mask: net.CIDRMask(0, 32),
}
} else { // IPv6
route.Dst = &net.IPNet{
IP: net.IPv6zero,
Mask: net.CIDRMask(0, 128),
}
}
}
logger.Info.Printf("Route-Update: [%s] %s via %s", routeUpdateTypeMapFromId[routeUpdate.Type], route.Dst, route.Gw)
// Get wgDevice
wgDevice, err := client.Device(iface)
if err != nil {
logger.Error.Fatalf("Couldn't get wg-interface '%s' while running: %s", iface, err)
}
// Empty config for filling in switch
var wgConfig wgtypes.Config
switch routeUpdate.Type{
case unix.RTM_NEWROUTE:
// Check if gateway is set
if route.Gw == nil{
logger.Warn.Printf("Gateway unset, ignoring")
continue
}
// Check if other peer already has exact same dst
if peer, err := wgChecks.PeerByIPNet(&wgDevice.Peers, route.Dst); err == nil {
logger.Warn.Printf("dst-IPNet already set for Peer '%s', ignoring", peer.PublicKey)
continue
}
// Get peer containing gateway-addr
peer, err := wgChecks.PeerByIP(&wgDevice.Peers, &route.Gw)
if(err != nil){
logger.Warn.Printf("No peer found containing gw-IP '%s', ignoring", route.Gw)
continue
}
// Set peerConfig, this will override set values for that peer
wgConfig.Peers = []wgtypes.PeerConfig{
{
PublicKey: peer.PublicKey,
AllowedIPs: append(peer.AllowedIPs, *route.Dst),
},
}
case unix.RTM_DELROUTE:
// Get peer containing dst-NetIP
peerIndex, ipNetIndex, err := wgChecks.PeerIndexByIPNet(&wgDevice.Peers, route.Dst)
if(err != nil){
logger.Warn.Printf("No peer found having dst-IPNet '%s', ignoring", route.Dst)
continue
}
peer := wgDevice.Peers[peerIndex]
// Delete dstNet from allowedIPs
peer.AllowedIPs[ipNetIndex] = peer.AllowedIPs[len(peer.AllowedIPs)-1]
peer.AllowedIPs = peer.AllowedIPs[:len(peer.AllowedIPs)-1]
// Set peerConfig, this will override set values for that peer
wgConfig.Peers = []wgtypes.PeerConfig{
{
PublicKey: peer.PublicKey,
UpdateOnly: true,
ReplaceAllowedIPs: true,
AllowedIPs: peer.AllowedIPs,
},
}
}
err = client.ConfigureDevice(iface, wgConfig)
if(err != nil){
logger.Error.Fatalf("Error configuring wg-device '%s': %s", iface, err)
}
}
}

28
doc/add-route.puml Normal file
View File

@@ -0,0 +1,28 @@
@startuml
autonumber
hide footbox
footer "RoutingTableToWg | Ruakij"
title "Add Route"
participant System
control Program
boundary Wireguard
System ++
Wireguard ++
System ->> Program ++ : Add Route
Program -> Program : Filter Route
Program -> Wireguard ++ : Get current State
Wireguard -> Program -- : State
Program -> Program : Find Peer with Gateway\nfrom AllowedIPs
Program -> Wireguard ++ : Add Dst-Net to\nAllowedIPs from Peer
Wireguard --> Program --
Program --
@enduml

436
doc/add-route.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 22 KiB

28
doc/del-route.puml Normal file
View File

@@ -0,0 +1,28 @@
@startuml
autonumber
hide footbox
footer "RoutingTableToWg | Ruakij"
title "Delete Route"
participant System
control Program
boundary Wireguard
System ++
Wireguard ++
System ->> Program ++ : Delete Route
Program -> Program : Filter Route
Program -> Wireguard ++ : Get current State
Wireguard -> Program -- : State
Program -> Program : Find Peer with Dst-Net\nfrom AllowedIPs
Program -> Wireguard ++ : Remove Dst-Net from\nAllowedIPs from Peer
Wireguard --> Program --
Program --
@enduml

436
doc/del-route.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 22 KiB

22
go.mod Normal file
View File

@@ -0,0 +1,22 @@
module git.ruekov.eu/ruakij/routingtabletowg
go 1.19
require (
github.com/vishvananda/netlink v1.1.0
golang.org/x/sys v0.6.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230215201556-9c5414ab4bde
)
require (
github.com/google/go-cmp v0.5.9 // indirect
github.com/josharian/native v1.1.0 // indirect
github.com/mdlayher/genetlink v1.3.1 // indirect
github.com/mdlayher/netlink v1.7.1 // indirect
github.com/mdlayher/socket v0.4.0 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b // indirect
)

29
go.sum Normal file
View File

@@ -0,0 +1,29 @@
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/mdlayher/genetlink v1.3.1 h1:roBiPnual+eqtRkKX2Jb8UQN5ZPWnhDCGj/wR6Jlz2w=
github.com/mdlayher/genetlink v1.3.1/go.mod h1:uaIPxkWmGk753VVIzDtROxQ8+T+dkHqOI0vB1NA9S/Q=
github.com/mdlayher/netlink v1.7.1 h1:FdUaT/e33HjEXagwELR8R3/KL1Fq5x3G5jgHLp/BTmg=
github.com/mdlayher/netlink v1.7.1/go.mod h1:nKO5CSjE/DJjVhk/TNp6vCE1ktVxEA8VEh8drhZzxsQ=
github.com/mdlayher/socket v0.4.0 h1:280wsy40IC9M9q1uPGcLBwXpcTQDtoGwVt+BNoITxIw=
github.com/mdlayher/socket v0.4.0/go.mod h1:xxFqz5GRCUN3UEOm9CZqEJsAbe1C8OwSK46NlmWuVoc=
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws=
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b h1:J1CaxgLerRR5lgx3wnr6L04cJFbWoceSK9JWBdglINo=
golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b/go.mod h1:tqur9LnfstdR9ep2LaJT4lFUl0EjlHtge+gAjmsHUG4=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230215201556-9c5414ab4bde h1:ybF7AMzIUikL9x4LgwEmzhXtzRpKNqngme1VGDWz+Nk=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230215201556-9c5414ab4bde/go.mod h1:mQqgjkW8GQQcJQsbBvK890TKqUK1DfKWkuBGbOkuMHQ=

View File

@@ -0,0 +1,27 @@
package environmentchecks
import (
"os"
"fmt"
)
func HandleDefaults(envDefaults map[string]string){
for env, defaultValue := range envDefaults{
// Check if env is set
_, isSet := os.LookupEnv(env)
if(!isSet){
os.Setenv(env, defaultValue)
}
}
}
func HandleRequired(envRequired []string) error {
for _, env := range envRequired{
// Check if env is set
_, isSet := os.LookupEnv(env)
if(!isSet){
return fmt.Errorf("env '%s' required, but not set", env)
}
}
return nil
}

View File

@@ -0,0 +1,102 @@
package iproute2mapping
import (
"os"
"bufio"
"strings"
"strconv"
"fmt"
)
// Storage for mapping
var ByName = make(map[int]map[string]int)
var ById = make(map[int]map[int]string)
// Mapping types
const (
PROTOCOL = iota
TABLE
)
// Paths
var filePaths = map[int]string{
PROTOCOL: "/etc/iproute2/rt_protos",
TABLE: "/etc/iproute2/rt_tables",
}
// Export error-check
var Errors []error;
func init() {
var err error
for mapType, filePath := range filePaths{
ByName[mapType], ById[mapType], err = readFromFile(filePath)
if(err != nil){
Errors = append(Errors,
fmt.Errorf("failed reading mapping-file '%s': %s", filePath, err),
);
}
}
}
func readFromFile(filePath string) (mapByName map[string]int, mapById map[int]string, err error){
file, err := os.Open(filePath)
if(err != nil){
return nil, nil, err;
}
defer file.Close()
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
mapByName = make(map[string]int)
mapById = make(map[int]string)
// Go through file line-by-line
for scanner.Scan() {
text := scanner.Text()
if(text == "" || strings.HasPrefix(text, "#")){
continue
}
id, name, err := getMappingFromText(text)
if(err != nil){
// Only warn as we can continue processing the file
Errors = append(Errors,
fmt.Errorf("mappig-data invalid '%s': %s", text, err),
)
continue
}
mapByName[name] = id
mapById[id] = name
}
return
}
func getMappingFromText(text string) (int, string, error) {
// Split and read/convert data
data := strings.Split(text, "\t")
id, err := strconv.Atoi(data[0])
if(err != nil){
return 0, "", err
}
return id, data[1], nil
}
// Try getting an id from a name (or a string containing an id) with a specified type
func TryGetId(mappingType int, name string) (int, error){
// Try to convert name to id
id, err := strconv.Atoi(name)
if(err != nil){ // name given -> Convert to id
var found bool
id, found = ByName[mappingType][name]
if(!found){
return 0, fmt.Errorf("no id found from name")
}
}
return id, nil
}

View File

@@ -0,0 +1,2 @@
package iproute2mapping

View File

@@ -0,0 +1,25 @@
package netchecks
import (
"fmt"
"net"
"reflect"
)
func IPNetIndexByIP(list *[]net.IPNet, ip *net.IP) (int, error) {
for index, ipNetEntry := range *list {
if ipNetEntry.Contains(*ip) {
return index, nil
}
}
return -1, fmt.Errorf("ip not in ipNet-list")
}
func IPNetIndexByIPNet(list *[]net.IPNet, ipNet *net.IPNet) (int, error) {
for index, ipNetEntry := range *list {
if reflect.DeepEqual(ipNetEntry, *ipNet) {
return index, nil
}
}
return -1, fmt.Errorf("ipNet not in ipNet-list")
}

42
lib/wgchecks/wgchecks.go Normal file
View File

@@ -0,0 +1,42 @@
package wgChecks
import (
"fmt"
"net"
"git.ruekov.eu/ruakij/routingtabletowg/lib/wgchecks/netchecks"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
func PeerIndexByIP(peers *[]wgtypes.Peer, ip *net.IP) (int, int, error) {
for index, peer := range *peers {
if ipIndex, err := netchecks.IPNetIndexByIP(&peer.AllowedIPs, ip); err == nil {
return index, ipIndex, nil
}
}
return -1, -1, fmt.Errorf("no peer by ip in list")
}
func PeerByIP(peers *[]wgtypes.Peer, ip *net.IP) (*wgtypes.Peer, error) {
index, _, err := PeerIndexByIP(peers, ip)
if(err != nil) {
return nil, err
}
return &(*peers)[index], nil
}
func PeerIndexByIPNet(peers *[]wgtypes.Peer, ipNet *net.IPNet) (int, int, error) {
for index, peer := range *peers {
if ipNetIndex, err := netchecks.IPNetIndexByIPNet(&peer.AllowedIPs, ipNet); err == nil {
return index, ipNetIndex, nil
}
}
return -1, -1, fmt.Errorf("no peer by ipNet in list")
}
func PeerByIPNet(peers *[]wgtypes.Peer, ipNet *net.IPNet) (*wgtypes.Peer, error) {
index, _, err := PeerIndexByIPNet(peers, ipNet)
if(err != nil) {
return nil, err
}
return &(*peers)[index], nil
}