{"id":16991039,"url":"https://github.com/gin66/wg_netmanager","last_synced_at":"2025-03-22T15:30:58.207Z","repository":{"id":51332972,"uuid":"443136229","full_name":"gin66/wg_netmanager","owner":"gin66","description":"Wireguard network manager","archived":false,"fork":false,"pushed_at":"2022-02-12T16:59:40.000Z","size":1483,"stargazers_count":13,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-18T13:15:31.494Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gin66.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-12-30T17:03:58.000Z","updated_at":"2024-03-31T13:14:19.000Z","dependencies_parsed_at":"2022-09-10T21:03:02.349Z","dependency_job_id":null,"html_url":"https://github.com/gin66/wg_netmanager","commit_stats":null,"previous_names":[],"tags_count":41,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gin66%2Fwg_netmanager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gin66%2Fwg_netmanager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gin66%2Fwg_netmanager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gin66%2Fwg_netmanager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gin66","download_url":"https://codeload.github.com/gin66/wg_netmanager/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244978508,"owners_count":20541862,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-14T03:24:38.817Z","updated_at":"2025-03-22T15:30:57.759Z","avatar_url":"https://github.com/gin66.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"Wireguard network manager\n=========================\n\n# Motivation / Problem\n\nSituation is a couple of vps, some IoT devices in the home network and couple of roaming laptops/iPads/smartphones.  Till now a quite complex setup involving wireguard, openvpn, ssh'ing from box to box was in use.\n\nUsing wireguard all the time is not an option, because then the Laptop in the home network would route traffic to the box one meter away via the long route (the vps somewhere in the Internet), instead of using the short path within the home network.\n\nAn alternative could have been [tinc](https://tinc-vpn.org/), but tinc - licensed under GPL v2 - may never hit iOs/iPadOS AppStore. So not a solution.\n\n# Solution / Idea\n\nUse wireguard and add the missing management part. This shall:\n- bring up and configure wireguard devices\n- perform the key management/exchange\n- set up routes automagically\n- identify shorter routes\n\nInstead of manually creating keys (which is still the case in gui versions) the network uses one file to be distributed to all participants.  Here a work in progress example (filename net.yaml):\n\n```yaml\nnetwork:\n  sharedKey: YDUBM6FhERePZ4gPlxzAbCN7K61BPjy7HApWYL+P128=\n  subnet: 10.1.1.0/8\n\npeers:\n  - endPoint: 192.168.1.70:50000\n    adminPort: 55555\n    wgIp: 10.1.1.1\n  - endPoint: 192.168.1.212:50000\n    adminPort: 55555\n    wgIp: 10.1.1.2\n```\n\nThe sharedKey can be created with `wg genkey`.\n\n\nUnfortunately there is still the need to define at least ONE static peer.\n\nBring up e.g. alice, bob and charlie would be just:\n```\nALICE'S   BOX\u003e wg_netmanager -c net.yaml -i wg0 -a 10.1.1.1  -n alice\nBOB'S     BOX\u003e wg_netmanager -c net.yaml -i wg0 -a 10.1.1.16 -n bob\nCHARLIE'S BOX\u003e wg_netmanager -c net.yaml -i wg0 -a 10.1.1.21 -n charlie\n```\nwith alice being reachable on 192.168.1.70\n\n# Definitions/Nomenclatura\n\n- Node: Participant in the network\n- Peer: Node reachable directly via wireguard interface\n- Dynamic peer: synonym for peer\n- Static server: Fixed address/port either in internet or in intranet\n- Dynamic server: Any node (24/7) behind a firewall\n- Roaming client: Any node, which is switching IP-address\n- Mobile client: Roaming client with data volume limitation\n\n# Status\n\nNode support:\n- [X] Static server in config file\n- [X] Static server per dynamic dns\n- [ ] Static server per command line parameter\n- [X] Dynamic server\n- [X] Roaming client\n- [ ] Mobile client\n\nOS-Support\n- [X] Linux\n- [X] MacOS\n- [ ] Windows\n- [ ] iOS/iPadOS\n- [ ] Android\n- [ ] FreeBSD\n- [ ] OpenBSD\n- [X] Openwrt Linux\n\nWireguard-Interface\n- [X] Kernel-driver + Command ip/wg\n- [X] wiregard-go + Command ip/wg\n- [X] boringtun + Command ip/wg\n- [ ] boringtun (embedded) + ip\n\nNetwork\n- [X] Connection established between two static servers (fixed address)\n- [X] Connection established between dynamic node and static server\n- [X] Connection established between two dynamic nodes in same subnet\n- [X] Connection established between two dynamic nodes using their visible outside connections aka NAT traversal\n\nRouting\n- [X] Sets up routes to reach all network participants\n- [ ] Gateway feature of nodes\n\nSystem integration\n- [ ] systemd\n- [ ] rc-based system\n\nAdmin\n- [X] TUI interface\n- [ ] REST API\n- [ ] Web UI frontend\n\nAs it works on my setup, the development will now slow down and will focus more on bugfixing.\n\n# Working Example\n\nMy test setup is:\n\n```\n             Alpha-VPS          Internet       Beta-VPS\n          behind firewall ---------+---------  public IP\n                                   |\n                                   |\n                                   |\n                                 Router\n                                   |\n                      192.168.x.x  |\n            Charlie   ------------------------  Delta\n\n```\nAlpha-VPA and Beta-VPS use old linux version without wireguard kernel driver. So wireguard-go is in use.\n\n1. After start of wg_manager on all four machines, three wireguard connections are setup quickly:\n\n\t- Alpha-VPS \u003c=\u003e Beta-VPS\n\t- Charlie \u003c=\u003e Beta-VPS\n\t- Delta \u003c=\u003e Beta-VPS\n\n\tIn addition the following gateway rules are added:\n\t- Alpha-VPS ==\u003e Charlie/Delta via Gateway Beta-VPS\n\t- Charlie ==\u003e Alpha-VPS/Delta via Gateway Beta-VPS\n\t- Delta ==\u003e Alpha-VPS/Charlie via Gateway Beta-VPS\n\n2. Shortly afterwards Charlie/Delta discover the local connection possibility. So the wireguard connections/routes change to:\n\n\t- Alpha-VPS \u003c=\u003e Beta-VPS\n\t- Charlie \u003c=\u003e Beta-VPS\n\t- Delta \u003c=\u003e Beta-VPS\n\t- Charlie \u003c=\u003e Delta\n\n\t- Alpha-VPS ==\u003e Charlie/Delta via Gateway Beta-VPS\n\t- Charlie ==\u003e Alpha-VPS via Gateway Beta-VPS\n\t- Delta ==\u003e Alpha-VPS via Gateway Beta-VPS\n\n3. After the one or other minute, NAT traversal is set up. And only wireguard connections exist without any gateway:\n\n\t- Alpha-VPS \u003c=\u003e Beta-VPS\n\t- Alpha-VPS \u003c=\u003e Charlie\n\t- Alpha-VPS \u003c=\u003e Delta\n\t- Charlie \u003c=\u003e Beta-VPS\n\t- Charlie \u003c=\u003e Delta\n\t- Delta \u003c=\u003e Beta-VPS\n\nActually, the tendency to go to one-to-one connections causes a new problem. The required amount of keep alive packages (to keep firewall ports persistent) between nodes increases nearly quadratically with the number of nodes in the net....\n\nNot so much a problem in my setup, but still something to be addressed in the long run.\n\n# Another working Example\n\nA second setup is:\n\n```\n             Alpha-VPS          Internet       Beta-VPS\n          behind firewall ---------+---------  public IP\n                                   |\n                                   |\n                                   |\n                            =====Router 1====Masquerade+Firewall\n                                   |\n                      192.168.1.x  |\n            Charlie   -------------+----------  Delta\n                                   |\n                                   |\n                            =====Router 2====Masquerade+Firewall\n                      192.168.2.x  |\n```\n\n# Installation\n\nWith rust installed, just issue\n```\n\tcargo install wg_netmanager\n```\n\n## Linux\n\nThe packages wireguard-tools and iproute/iproute2 need to be installed.\n\nIf kernel driver does not exist (e.g. VPS), then either `wireguard-go` or `boringtun` should be installed and in the path (using `sudo`).\n\n## Macos\n\nThe packages wireguard-tools and wireguard-go need to be installed e.g. via brew.\n\n## Openwrt\n\nThe package wireguard-tools and kmod-wireguard need to be installed:\n```\n\topkg install wireguard-tools kmod-wireguard\n```\n\n# Usage\n\nGenerally, a shared key needs to be created and stored under sharedKey in your local copy of network.yaml. This can be done by:\n```\n\twg genkey\n```\nand copy the result in the network.yaml\n\nThen modify the peers list to accommodate your setup. At least one peer with a static address is needed. For dyndns-reachable servers, use the hostname instead of an ip.\n\nIf the subnet 10.1.1.0/8 does not suit your needs, then change it. All wireguard IPs need to be included in the chosen subnet.\n\nThen copy the final yaml file to all your nodes and start the wg_netmanager with:\n```\n\twg_netmanager -c network.yaml \u003cwireguard-interface\u003e \u003cwireguard-ip\u003e \u003cname\u003e\n```\nor - in case your sudo requires password:\n```\n\tsudo wg_netmanager -c network.yaml \u003cwireguard-interface\u003e \u003cwireguard-ip\u003e \u003cname\u003e\n```\n\n\nEventually use further `-v` or a `-t`.\n\nFor vps, which do not support wireguard as network interface, either boringtun or wireguard-go can be used. wg_netmanager will try to run first wireguard-go and then boringtun. If this fails, but wireguard interface can be created by other means, then inform wg_netmanager about the existing wireguard interface with the `-e` commandline switch.\n\nFor a list of commandline options, just use `--help` as usual.\n\nThe required command line options for wireguard interface (-i), address (-a) and name (-n), can be stored in a peer.yaml file like this:\n```ỳaml\n\tname: alice\n\twgIp: 10.1.1.1\n\twgInterface: wg0\n\texistingInterface: false\n```\nThe last one is actually only needed, if set to true.\n\n# Testing\n\nUsing namespaces several boxes can be simulated on one linux machine.\nSee as [example](https://github.com/gin66/wg_netmanager/blob/main/ns/three_boxes.sh)\n\n# Technical Background\n\nwg_manager will add and delete routes on demand on two levels:\n- As routing policy of the kernel using `ip route add \u003cip\u003e/32 dev \u003cwg_dev\u003e`\n- If a node is directly reachable, by adding a peer entry in the wireguard configuration\n  with a list of allowed ip's. This list includes the peer and all further nodes, for which this peer can forward traffic to.\n\n# Security Consideration\n\nIn case one node of this wireguard network is compromised, then the implications are severe. The symmetric key can be distributed and any attacker's node can join the network.\n\nWith the current implementation an attacker could even issue this command:\n```\nATTACKER'S BOX\u003e wg_netmanager -c net.yaml wg0 8.8.8.8  alice\n```\nAnd ALL network participants will start to route any DNS request addressed to 8.8.8.8 to the ATTACKER's box.\n\nThis is actually a very cool feature and on the other hand quite frightening.\n\n\n## Update\n\nDepending on the linux version, `ip route add` wants to find an interface with the corresponding subnet. If not successful, then it will throw a \"no such process error\".\n\nRemedy is, that the wireguard interface is associated with IP and resp. netmask. without adding a route:\n```\n  ip addr add 10.1.1.1/24 dev wg0 noprefixroute\n```\n\nConsequently, in the config-file the subnet has to specified. If the subnet does not include 8.8.8.8, then other nodes will not accept it - unless the defined subnet includes 8.8.8.8\n\n# License\n\nThe code of this crate is licensed according to MIT. To learn about the licenses of included crates, please check `cargo license`.\n\n# Lessons Learned\n\n- Spent half a day figuring out, why udp socket connection has been working, tunnel in wireguard configuration on both peers have been properly setup, but tunnel was not working. At some point I have recognized, that the working nodes were in the internet and the failing ones in the local subnet. Rebooting the internet router solved this issue\n- Update: Apparently the router does not like the usage of the same udp-ports aka the need for translation in the router firewall.\n- Update 2: If one client in local subnet reuses the same wireguard port, the communication cannot be established. If the wireguard port is changed, it starts working again.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgin66%2Fwg_netmanager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgin66%2Fwg_netmanager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgin66%2Fwg_netmanager/lists"}