{"id":50937981,"url":"https://github.com/simula/dynmhs","last_synced_at":"2026-06-17T11:03:34.531Z","repository":{"id":261747507,"uuid":"885202829","full_name":"simula/dynmhs","owner":"simula","description":"Dynamic Multi-Homing Setup","archived":false,"fork":false,"pushed_at":"2026-06-11T16:29:39.000Z","size":1093,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-06-11T18:15:23.333Z","etag":null,"topics":["autoconfig","dhcp","dhcpv6","ip","ipv4","ipv6","multi-homing","routing","rules"],"latest_commit_sha":null,"homepage":"https://www.nntb.no/~dreibh/dynmhs/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simula.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-11-08T06:36:57.000Z","updated_at":"2026-06-11T16:29:43.000Z","dependencies_parsed_at":"2024-11-08T08:23:05.452Z","dependency_job_id":"b3f13bd6-15aa-4944-910b-125bf753e437","html_url":"https://github.com/simula/dynmhs","commit_stats":null,"previous_names":["simula/dynmhs"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/simula/dynmhs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simula%2Fdynmhs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simula%2Fdynmhs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simula%2Fdynmhs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simula%2Fdynmhs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simula","download_url":"https://codeload.github.com/simula/dynmhs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simula%2Fdynmhs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34445186,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-17T02:00:05.408Z","response_time":127,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["autoconfig","dhcp","dhcpv6","ip","ipv4","ipv6","multi-homing","routing","rules"],"created_at":"2026-06-17T11:03:20.747Z","updated_at":"2026-06-17T11:03:34.522Z","avatar_url":"https://github.com/simula.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n Dynamic Multi-Homing Setup\u0026nbsp;(DynMHS)\u003cbr /\u003e\n \u003cspan style=\"font-size: 75%;\"\u003eA Tool for the Dynamic Setup of Multi-Homing IP Routing Rules\u003c/span\u003e\u003cbr /\u003e\n \u003ca href=\"https://www.nntb.no/~dreibh/dynmhs/\"\u003e\n  \u003cimg alt=\"DynMHS Logo\" src=\"src/figures/Logo-DynMHS.svg\" width=\"25%\" /\u003e\u003cbr /\u003e\n  \u003cspan style=\"font-size: 75%;\"\u003ehttps://www.nntb.no/~dreibh/dynmhs\u003c/span\u003e\n \u003c/a\u003e\n\u003c/h1\u003e\n\n\n# 💡 What is DynMHS?\n\nDynamic Multi-Homing Setup\u0026nbsp;(DynMHS) dynamically sets up IP routing rules, to allow for using multiple network connections simultaneously. That is, for each relevant network interface, a separate routing table is created and maintained. For each source address of a network interface managed by DynMHS, routing rules are maintained to point to the corresponding routing table. Software binding to a specific interface address can then use a specific network. In addition, multi-homing-capable network protocols like the Multi-Path TCP\u0026nbsp;(MPTCP) or the Stream Control Transmission Protocol\u0026nbsp;(SCTP) can take advantage of multi-homing for redundancy and load balancing.\n\n\n# 😀 Example\n\n## Scenario\n\nA Linux PC is connected to two NAT networks, configuration is dynamic via IPv4 DHCP and IPv6 auto-configuration:\n\n* Network #1 on interface enp0s8: 172.30.255.4 / fdff:b44d:605c:0:a00:27ff:fedb:ad69\n* Network #2 on interface enp0s9: 192.168.255.4 / fdc9:dc25:8e35:0:a00:27ff:feaa:bc91\n\nNetwork settings for [Netplan](https://netplan.io/) (in `/etc/netplan/testpc.yaml`):\n```yaml\nnetwork:\n  version: 2\n  ethernets:\n    enp0s8:\n      accept-ra: true\n      dhcp4: true\n      dhcp4-overrides:\n        route-metric: 200\n    enp0s9:\n      accept-ra: true\n      dhcp4: true\n      dhcp4-overrides:\n        route-metric: 300\n```\n\n```bash\nsudo hipercontracer -P \\\n   -S 172.30.255.4 -S 192.168.255.4 \\\n   -S fdff:b44d:605c:0:a00:27ff:fedb:ad69 -S fdc9:dc25:8e35:0:a00:27ff:feaa:bc91 \\\n   -D 8.8.8.8 -D 2001:4860:4860::8888\n```\n\nIPv4 routes:\n\n\u003cpre\u003e\u003ccode\u003e\u003cspan style=\"color:red;\"\u003euser@host\u003c/span\u003e\u003cspan style=\"color:blue;\"\u003e:~\u003c/span\u003e\u003cspan style=\"color:gray;\"\u003e$\u003c/span\u003e \u003cspan class=\"ex\"\u003eip\u003c/span\u003e \u003cspan class=\"at\"\u003e-4\u003c/span\u003e route show\ndefault via 172.30.255.1 dev enp0s8 proto dhcp src 172.30.255.4 metric 200\ndefault via 192.168.255.1 dev enp0s9 proto dhcp src 192.168.255.4 metric 300\n172.30.255.0/24 dev enp0s8 proto kernel scope link src 172.30.255.4 metric 200\n172.30.255.1 dev enp0s8 proto dhcp scope link src 172.30.255.4 metric 200\n192.168.255.0/24 dev enp0s9 proto kernel scope link src 192.168.255.4 metric 300\n192.168.255.1 dev enp0s9 proto dhcp scope link src 192.168.255.4 metric 300\n\u003c/code\u003e\u003c/pre\u003e\n\nIPv6 routes:\n\n\u003cpre\u003e\u003ccode\u003e\u003cspan style=\"color:red;\"\u003euser@host\u003c/span\u003e\u003cspan style=\"color:blue;\"\u003e:~\u003c/span\u003e\u003cspan style=\"color:gray;\"\u003e$\u003c/span\u003e \u003cspan class=\"ex\"\u003eip\u003c/span\u003e \u003cspan class=\"at\"\u003e-6\u003c/span\u003e route show\nfc88:1::/64 dev hostonly101 proto kernel metric 256 linkdown pref medium\nfdc9:dc25:8e35::/64 dev enp0s9 proto ra metric 300 pref medium\nfdff:b44d:605c::/64 dev enp0s8 proto ra metric 200 pref medium\nfe80::/64 dev enp0s8 proto kernel metric 256 pref medium\nfe80::/64 dev enp0s9 proto kernel metric 256 pref medium\ndefault via fe80::5054:ff:fe12:3500 dev enp0s8 proto ra metric 200 expires 788sec pref medium\ndefault via fe80::5054:ff:fe12:3500 dev enp0s9 proto ra metric 300 expires 772sec pref medium\n\u003c/code\u003e\u003c/pre\u003e\n\nNote the two default routes with their different metrics (200, 300).\n\n## Why is this setup not working as expected?\n\nThe expectation is that, according to the chosen source address, a packet is routed via the corresponding interface (enp0s8 or enp0s9). This can be tested by using [HiPerConTracer](https://www.nntb.no/~dreibh/hipercontracer/), running HiPerConTracer Ping to the Google DNS servers (8.8.8.8, 2001:4860:4860::8888) from all four source addresses:\n\n\u003cpre\u003e\u003ccode\u003e\u003cspan style=\"color:red;\"\u003euser@host\u003c/span\u003e\u003cspan style=\"color:blue;\"\u003e:~\u003c/span\u003e\u003cspan style=\"color:gray;\"\u003e$\u003c/span\u003e \u003cspan class=\"fu\"\u003esudo\u003c/span\u003e hipercontracer \u003cspan class=\"at\"\u003e-P\u003c/span\u003e \\\n   \u003cspan class=\"at\"\u003e-S\u003c/span\u003e 172.30.255.4 \u003cspan class=\"at\"\u003e-S\u003c/span\u003e 192.168.255.4 \\\n   \u003cspan class=\"at\"\u003e-S\u003c/span\u003e fdff:b44d:605c:0:a00:27ff:fedb:ad69 \u003cspan class=\"at\"\u003e-S\u003c/span\u003e fdc9:dc25:8e35:0:a00:27ff:feaa:bc91 \\\n   \u003cspan class=\"at\"\u003e-D\u003c/span\u003e 8.8.8.8 \u003cspan class=\"at\"\u003e-D\u003c/span\u003e 2001:4860:4860::8888\n\u003c/code\u003e\u003c/pre\u003e\n\nConnectivity is always over the primary interface, i.e.\u0026nbsp;172.30.255.4 and\u0026nbsp;fdff:b44d:605c:0:a00:27ff:fedb:ad69. The reason is: This default route has the lowest metric! Also, simply using the same metric for both routes does *not* fix the issue. Then, just the first default route in the routing table would get used.\n\nTo get the setup working as expected, it is necessary to configure separate routing tables for each network, and routing rules to select a routing table according to the *source* IP address. For example:\n\n* Rule #2000: for packets from 172.30.255.4 use routing table #2000.\n* Rule #2000: for packets from fdff:b44d:605c:0:a00:27ff:fedb:ad69 use routing table #2000.\n* Rule #3000: for packets from 192.168.255.4 use routing table #3000.\n* Rule #3000: for packets from fdc9:dc25:8e35:0:a00:27ff:feaa:bc91 use routing table #3000.\n\nRules:\n\n\u003cpre\u003e\u003ccode\u003e\u003cspan style=\"color:red;\"\u003euser@host\u003c/span\u003e\u003cspan style=\"color:blue;\"\u003e:~\u003c/span\u003e\u003cspan style=\"color:gray;\"\u003e$\u003c/span\u003e \u003cspan class=\"ex\"\u003eip\u003c/span\u003e rule show\n0:      from all lookup local\n2000:   from 172.30.255.4 lookup 2000\n3000:   from 192.168.255.4 lookup 3000\n32766:  from all lookup main\n32767:  from all lookup default\n\n\u003cspan style=\"color:red;\"\u003euser@host\u003c/span\u003e\u003cspan style=\"color:blue;\"\u003e:~\u003c/span\u003e\u003cspan style=\"color:gray;\"\u003e$\u003c/span\u003e \u003cspan class=\"ex\"\u003eip\u003c/span\u003e \u003cspan class=\"at\"\u003e-6\u003c/span\u003e rule show\n0:      from all lookup local\n2000:   from fdff:b44d:605c:0:a00:27ff:fedb:ad69 lookup 2000\n3000:   from fdc9:dc25:8e35:0:a00:27ff:feaa:bc91 lookup 3000\n32766:  from all lookup main\n\u003c/code\u003e\u003c/pre\u003e\n\nTables:\n\n\u003cpre\u003e\u003ccode\u003e\u003cspan style=\"color:red;\"\u003euser@host\u003c/span\u003e\u003cspan style=\"color:blue;\"\u003e:~\u003c/span\u003e\u003cspan style=\"color:gray;\"\u003e$\u003c/span\u003e \u003cspan class=\"ex\"\u003eip\u003c/span\u003e route show table 2000\ndefault via 172.30.255.1 dev enp0s8 proto dhcp src 172.30.255.4 metric 200\n172.30.255.0/24 dev enp0s8 proto kernel scope link src 172.30.255.4 metric 200\n172.30.255.1 dev enp0s8 proto dhcp scope link src 172.30.255.4 metric 200\n\n\u003cspan style=\"color:red;\"\u003euser@host\u003c/span\u003e\u003cspan style=\"color:blue;\"\u003e:~\u003c/span\u003e\u003cspan style=\"color:gray;\"\u003e$\u003c/span\u003e \u003cspan class=\"ex\"\u003eip\u003c/span\u003e \u003cspan class=\"at\"\u003e-6\u003c/span\u003e route show table 2000\nfdff:b44d:605c::/64 dev enp0s8 proto ra metric 200 pref medium\nfe80::/64 dev enp0s8 proto kernel metric 256 pref medium\ndefault via fe80::5054:ff:fe12:3500 dev enp0s8 proto ra metric 200 pref medium\n\n\u003cspan style=\"color:red;\"\u003euser@host\u003c/span\u003e\u003cspan style=\"color:blue;\"\u003e:~\u003c/span\u003e\u003cspan style=\"color:gray;\"\u003e$\u003c/span\u003e \u003cspan class=\"ex\"\u003eip\u003c/span\u003e route show table 3000\ndefault via 192.168.255.1 dev enp0s9 proto dhcp src 192.168.255.4 metric 300\n192.168.255.0/24 dev enp0s9 proto kernel scope link src 192.168.255.4 metric 300\n192.168.255.1 dev enp0s9 proto dhcp scope link src 192.168.255.4 metric 300\n\n\u003cspan style=\"color:red;\"\u003euser@host\u003c/span\u003e\u003cspan style=\"color:blue;\"\u003e:~\u003c/span\u003e\u003cspan style=\"color:gray;\"\u003e$\u003c/span\u003e \u003cspan class=\"ex\"\u003eip\u003c/span\u003e \u003cspan class=\"at\"\u003e-6\u003c/span\u003e route show table 3000\nfdc9:dc25:8e35::/64 dev enp0s9 proto ra metric 300 pref medium\nfe80::/64 dev enp0s9 proto kernel metric 256 pref medium\ndefault via fe80::5054:ff:fe12:3500 dev enp0s9 proto ra metric 300 pref medium\n\u003c/code\u003e\u003c/pre\u003e\n\nIt would be possible to configure *static* rules/tables in Netplan. But DHCP and IPv6 auto-configuration use *dynamic* addresses. So, they may change!\n\n## Applying DynMHS\n\nDynamic Multi-Homing Setup\u0026nbsp;(DynMHS) is the solution for dynamically creating, adapting, and destroying routing tables and rules. DynMHS monitors the system's network configuration for changes, and applies the necessary settings for additional routing tables and the corresponding routing rules. This works for IPv4 and IPv6, including multiple addresses as well as additional routes over the monitored interfaces.\n\n### Manual usage\n\n```bash\nsudo dynmhs --network enp0s8:2000 --network enp0s9:3000 --loglevel 2\n```\n\n### Running as SystemD service\n\nConfiguration in `/etc/dynmhs/dynmhs.conf`:\n\n```bash\n# ====== Logging ============================================================\n# Logging verbosity (0=trace, 1=debug, 2=info, 3=warning, 4=error, 5=fatal):\nLOGLEVEL=2\n\n# Usage of colors for log output (ON or OFF):\nLOGCOLOR=ON\n\n# Custom logfile:\n# LOGFILE=\"/var/log/dynmhs.log\"\n\n# ====== Networks ===========================================================\nNETWORK=\"enp0s8:2000\"\nNETWORK=\"enp0s9:3000\"\n```\n\nThese settings map interface enp0s8 to routing table #2000, and interface enp0s9 to routing table #3000. DynMHS will maintain the tables, and the corresponding rules. Note: more `NETWORK=` lines can be added as necessary.\n\nTo enable and start the DynMHS service:\n\n```bash\nsudo systemctl daemon-reload\nsudo systemctl enable dynmhs\nsudo systemctl start dynmhs\n```\n\nTo observe the logs of the DynMHS service:\n\n```bash\nsudo journalctl -f -u dynmhs\n```\n\n### A HiPerConTracer Ping test\n\nAnother test with [HiPerConTracer](https://www.nntb.no/~dreibh/hipercontracer/), running HiPerConTracer Ping to the Google DNS servers from all four source addresses:\n\n\u003cpre\u003e\n\u003cspan style=\"color:red;\"\u003euser@host\u003c/span\u003e\u003cspan style=\"color:blue;\"\u003e:~\u003c/span\u003e\u003cspan style=\"color:gray;\"\u003e$\u003c/span\u003e sudo hipercontracer -P \\\n   -S 172.30.255.4 -S 192.168.255.4 \\\n   -S fdff:b44d:605c:0:a00:27ff:fedb:ad69 -S fdc9:dc25:8e35:0:a00:27ff:feaa:bc91 \\\n   -D 8.8.8.8 -D 2001:4860:4860::8888\n...\n2025-02-28 13:59:50.422: Ping ICMP  192.168.255.4                           8.8.8.8                                 Success  s: 27µs q:  4µs r: 54µs  A:8.892ms   S:8.808ms   H:---\n2025-02-28 13:59:50.422: Ping ICMP  fdff:b44d:605c:0:a00:27ff:fedb:ad69     2001:4860:4860::8888                    Success  s: 51µs q:  6µs r:246µs  A:8.634ms   S:8.331ms   H:---\n2025-02-28 13:59:50.422: Ping ICMP  172.30.255.4                            8.8.8.8                                 Success  s: 38µs q:  4µs r:125µs  A:9.272ms   S:9.105ms   H:---\n2025-02-28 13:59:50.422: Ping ICMP  fdc9:dc25:8e35:0:a00:27ff:feaa:bc91     2001:4860:4860::8888                    Success  s: 29µs q:  2µs r:162µs  A:8.651ms   S:8.458ms   H:---\n...\n\u003c/pre\u003e\n\nNow, there is connectivity over both interfaces!\n\n\n# 📦 Binary Package Installation\n\nPlease use the issue tracker at [https://github.com/simula/dynmhs/issues](https://github.com/simula/dynmhs/issues) to report bugs and issues!\n\n## Ubuntu Linux\n\nFor ready-to-install Ubuntu Linux packages of DynMHS, see [Launchpad PPA for Thomas Dreibholz](https://launchpad.net/~dreibh/+archive/ubuntu/ppa/+packages?field.name_filter=dynmhs\u0026field.status_filter=published\u0026field.series_filter=)!\n\n```bash\nsudo apt-add-repository -sy ppa:dreibh/ppa\nsudo apt-get update\nsudo apt-get install dynmhs\n```\n\n## Fedora Linux\n\nFor ready-to-install Fedora Linux packages of DynMHS, see [COPR PPA for Thomas Dreibholz](https://copr.fedorainfracloud.org/coprs/dreibh/ppa/package/dynmhs/)!\n\n```bash\nsudo dnf copr enable -y dreibh/ppa\nsudo dnf install dynmhs\n```\n\n\n# 💾 Build from Sources\n\nDynMHS is released under the [GNU General Public Licence\u0026nbsp;(GPL)](https://www.gnu.org/licenses/gpl-3.0.en.html#license-text).\n\nPlease use the issue tracker at [https://github.com/simula/dynmhs/issues](https://github.com/simula/dynmhs/issues) to report bugs and issues!\n\n## Development Version\n\nThe Git repository of the DynMHS sources can be found at [https://github.com/simula/dynmhs](https://github.com/simula/dynmhs):\n\n```bash\ngit clone https://github.com/simula/dynmhs\ncd dynmhs\nsudo ci/get-dependencies --install\ncmake .\nmake\n```\n\nOptionally, for installation to the standard paths (usually under `/usr/local`):\n\n```bash\nsudo make install\n```\n\nNote: The script [`ci/get-dependencies`](https://github.com/simula/dynmhs/blob/master/ci/get-dependencies) automatically  installs the build dependencies under Debian/Ubuntu Linux, Fedora Linux, and FreeBSD. For manual handling of the build dependencies, see the packaging configuration in [`debian/control`](https://github.com/simula/dynmhs/blob/master/debian/control) (Debian/Ubuntu Linux), and [`dynmhs.spec`](https://github.com/simula/dynmhs/blob/master/rpm/dynmhs.spec) (Fedora Linux).\n\nContributions:\n\n* Issue tracker: [https://github.com/simula/dynmhs/issues](https://github.com/simula/dynmhs/issues).\n  Please submit bug reports, issues, questions, etc. in the issue tracker!\n\n* Pull Requests for DynMHS: [https://github.com/simula/dynmhs/pulls](https://github.com/simula/dynmhs/pulls).\n  Your contributions to DynMHS are always welcome!\n\n* CI build tests of DynMHS: [https://github.com/simula/dynmhs/actions](https://github.com/simula/dynmhs/actions).\n\n## Release Versions\n\nSee [https://www.nntb.no/~simula/dynmhs/#current-stable-release](https://www.nntb.no/~simula/dynmhs/#current-stable-release) for the release packages!\n\n\n# 🔗 Useful Links\n\n* [HiPerConTracer – High-Performance Connectivity Tracer](https://www.nntb.no/~dreibh/hipercontracer/)\n* [NetPerfMeter – A TCP/MPTCP/UDP/SCTP/DCCP Network Performance Meter Tool](https://www.nntb.no/~dreibh/netperfmeter/)\n* [SubNetCalc – An IPv4/IPv6 Subnet Calculator](https://www.nntb.no/~dreibh/dynmhs/)\n* [System-Tools – Tools for Basic System Management](https://www.nntb.no/~dreibh/system-tools/)\n* [Virtual Machine Image Builder and System Installation Scripts](https://www.nntb.no/~dreibh/vmimage-builder-scripts/)\n* [Wireshark](https://www.wireshark.org/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimula%2Fdynmhs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimula%2Fdynmhs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimula%2Fdynmhs/lists"}