{"id":20155876,"url":"https://github.com/bruj0/proxmoxipv6","last_synced_at":"2025-07-02T09:04:20.184Z","repository":{"id":169550630,"uuid":"425367506","full_name":"bruj0/ProxmoxIPv6","owner":"bruj0","description":"Fully routed IPv6 on Promox and Docker with WireGuard as IPv4to6 tunnel","archived":false,"fork":false,"pushed_at":"2023-06-16T19:41:02.000Z","size":1476,"stargazers_count":102,"open_issues_count":2,"forks_count":17,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-09T22:28:58.444Z","etag":null,"topics":["docker","ipv6","proxmox","wireguard"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bruj0.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2021-11-06T23:05:24.000Z","updated_at":"2025-04-04T20:44:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"4523abf2-a1e6-4ab6-b57d-c1b22a6127c0","html_url":"https://github.com/bruj0/ProxmoxIPv6","commit_stats":null,"previous_names":["bruj0/proxmoxipv6"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bruj0/ProxmoxIPv6","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bruj0%2FProxmoxIPv6","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bruj0%2FProxmoxIPv6/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bruj0%2FProxmoxIPv6/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bruj0%2FProxmoxIPv6/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bruj0","download_url":"https://codeload.github.com/bruj0/ProxmoxIPv6/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bruj0%2FProxmoxIPv6/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263108803,"owners_count":23415004,"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":["docker","ipv6","proxmox","wireguard"],"created_at":"2024-11-13T23:36:27.012Z","updated_at":"2025-07-02T09:04:20.164Z","avatar_url":"https://github.com/bruj0.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\n- [Description](#description)\n  - [Objectives](#objectives)\n  - [Diagram](#diagram)\n- [Networking](#networking)\n  - [Routes](#routes)\n  - [Ranges](#ranges)\n    - [IPv4](#ipv4)\n    - [IPv6](#ipv6)\n- [Proxmox Install](#proxmox-install)\n  - [Download and install utilities](#download-and-install-utilities)\n  - [Boot the installer and access it via VNC](#boot-the-installer-and-access-it-via-vnc)\n  - [After install](#after-install)\n  - [Optional settings](#optional-settings)\n  - [Proxmox configuration](#proxmox-configuration)\n  - [Bridges and Network interfaces](#bridges-and-network-interfaces)\n  - [Proxmox interface configuration](#proxmox-interface-configuration)\n- [Firewall VM (OpnSense)](#firewall-vm-opnsense)\n  - [Interfaces assignments in pfSense](#interfaces-assignments-in-pfsense)\n    - [LAN6 (WAN)](#lan6-wan)\n    - [LAN](#lan)\n    - [WireGuard](#wireguard)\n    - [Proxmox KVM](#proxmox-kvm)\n    - [Home network](#home-network)\n    - [Routing in OPNSense](#routing-in-opnsense)\n    - [Firewall Rules](#firewall-rules)\n    - [LAN DHCPv6](#lan-dhcpv6)\n- [Create a Debian template](#create-a-debian-template)\n- [VM configuration](#vm-configuration)\n- [Docker configuration](#docker-configuration)\n\n# Description\nThis howto will help you set up a Proxmox host with a fully routed IPv4 and IPv6 network for VMs with an out of band firewall.\n\nPoint to Point internal networks will help route IP traffic between the public internet an our internal network avoiding ARP resolution, `169.254.0.0/16` and `range::1/80`\n## Objectives \n* Fully routed IPv6 and NATed IPv4 to VMs\n   * Each VM will receive a IPv6 from a /77 subnet\n     * Each container under this VM will receive an IPv6 automatically.\n* IPv4 to IPv6 Tunnel using WireGuard\n* Out of band Firewall\n   * PfSense controlling the access to all public traffic\n   * Having an out of band firewall, meaning outside of the VMs. This will increase the security of the system\n## Diagram\n![Diagram](images/ProxmoxIPv6v2.drawio.png)\n\n\n# Networking\n## Routes\nIPv4 internal NAT: \n- 169.254.0.0/16 dev vmbr0 src 169.254.0.1 (vmbr0)\n- 172.16.0.0/16 via 169.254.0.2 (FW LAN) dev vmbr0 \n\nIPv6:\n- range::2 dev eth0  (eth0)\n- range::3 dev vmbr0 (vmbr0)\n- range::4 dev vmbr0 (FW WAN)\n- range::/64 via range::4 dev vmbr0\n- default via fe80::1 dev eth0 \n\n## Ranges\n### IPv4\n* Host:\n  * eth0: Public IP\n    * Port forward to VMs\n  * vmbr0: 169.254.0.1/16 (Host to WAN and NAT)\n    * Routes 172.16.0.0/16 via 169.254.0.2 (Firewall WAN)\n\n* Firewall VM:\n  * LAN: 172.16.0.1/16\n  * WAN: 169.254.0.2/16\n    * Rotes 0.0.0.0 via 169.254.0.2\n### IPv6\n* Host\n  * eth0: range::2/128 (eth0)\n  * vmbr0: range::3/128 (vmbr0)\n    * range::4 dev vmbr0  (Firewall)\n    * range::/64 via range::4\n\n* Firewall VM\n  * WAN: range::4/128\n  * LAN: range::/64 (Divided in 65536 /80)\n    * range:1::/80 (Reserved for Host to Firewall)\n    * range:2::/80 (WireGuard Tunnel)\n    * range:3::/80 (VMs main IP)\n    * range:4-ffff:/80 (Docker networks)\n\n# Proxmox Install\nFor normal install go to: https://www.proxmox.com/en/proxmox-ve/get-started\n\nTo install remotely boot into a rescue system with QEMU support.\n\n## Download and install utilities\n```\napt -y install ovmf wget \nwget -O pve.iso http://download.proxmox.com/iso/proxmox-ve_7.4-1.iso\n```\n## Boot the installer and access it via VNC\nChange the password and the disk devices\n\n```\nprintf \"change vnc password\\n%s\\n\" \"password\" | qemu-system-x86_64 -enable-kvm -cpu host -smp 4 -m 4096 -boot d -cdrom ./pve.iso -drive file=/dev/sda,format=raw,media=disk,if=virtio -drive file=/dev/sdb,format=raw,media=disk,if=virtio -vnc :0,password -monitor stdio -no-reboot\n```\nConnect to your public IP to port 5900 and the password you selected.\n\n## After install\nRun it under QEMU once more.\n\n```\nprintf \"change vnc password\\n%s\\n\" \"password\" | qemu-system-x86_64 -enable-kvm -cpu host -smp 4 -m 4096 -boot d -drive file=/dev/sda,format=raw,media=disk,if=virtio -drive file=/dev/sdb,format=raw,media=disk,if=virtio -vnc :0,password -monitor stdio -no-reboot\n```\nConnect via VNC once again and change the following:\n```\nnano /etc/default/grub\n\n# Edit this to disable \"predictable\" network interfaces, so the first interface is always eth0\n#GRUB_CMDLINE_LINUX_DEFAULT=\"net.ifnames=0 biosdevname=0\"\n# Then run\nupdate-grub\n\nnano /etc/network/interfaces\n# Change brodge-ports from ens3 to eth0\n\n# Create a swapfile if you are NOT using ZFS\nfallocate -l 8G /swapfile\nchmod 600 /swapfile\nmkswap /swapfile\necho \"/swapfile swap swap defaults 0 0\" \u003e\u003e /etc/fstab\n\n# Create ZFS volume for swap\n zfs create -V 8G -b $(getconf PAGESIZE) -o compression=zle \\\n              -o logbias=throughput -o sync=always\\\n              -o primarycache=metadata -o secondarycache=none \\\n              -o com.sun:auto-snapshot=false rpool/swap\n\n# Prepare it as swap partition:\nmkswap -f /dev/zvol/rpool/swap\nswapon /dev/zvol/rpool/swap\n\n# Add it to fstab\necho \"/dev/zvol/rpool/swap none swap discard 0 0\" \u003e\u003e /etc/fstab\n```\nReboot into Promox and change /etc/network/interfaces as shown in [Proxmox interface configuration](#proxmox-interface-configuration)\n\n\n## Optional settings\n\n```\nsystemctl disable --now rpcbind rpcbind.socket\nsed -i 's/^\\([^#].*\\)/# \\1/g' /etc/apt/sources.list.d/pve-enterprise.list\necho \"deb [arch=amd64] http://download.proxmox.com/debian/pve bullseye pve-no-subscription\" \u003e /etc/apt/sources.list.d/pve-no-subscription-repo.list\nsed -i \"s|ftp.*.debian.org|ftp.debian.org|g\" /etc/apt/sources.list\napt update \u0026\u0026 apt -y upgrade \u0026\u0026 apt -y autoremove\npveupgrade\nsed -Ezi.bak \"s/(Ext.Msg.show\\(\\{\\s+title: gettext\\('No valid sub)/void\\(\\{ \\/\\/\\1/g\" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js \u0026\u0026 systemctl restart pveproxy.service\napt install -y libguestfs-tools unzip iptables-persistent\napt install net-tools\necho \"nf_conntrack\" \u003e\u003e /etc/modules\necho \"net.ipv4.ip_forward=1\" \u003e\u003e /etc/sysctl.d/99-proxmox.conf\necho \"net.ipv6.conf.all.forwarding=1\" \u003e\u003e /etc/sysctl.d/99-proxmox.conf\necho \"net.netfilter.nf_conntrack_max=1048576\" \u003e\u003e /etc/sysctl.d/99-proxmox.conf\necho \"net.netfilter.nf_conntrack_tcp_timeout_established=28800\" \u003e\u003e /etc/sysctl.d/99-proxmox.conf\n# ZFS memory limits\necho \"options zfs zfs_arc_min=$[6 * 1024*1024*1024]\" \u003e\u003e /etc/modprobe.d/99-zfs.conf\necho \"options zfs zfs_arc_max=$[12 * 1024*1024*1024]\" \u003e\u003e /etc/modprobe.d/99-zfs.conf\nupdate-initramfs -u\n```\n\n## Proxmox configuration\nWe will need a way to provision VMs, for this article we selected Proxmox\nMore information: \n* https://www.proxmox.com/en/proxmox-ve/get-started\n\n\n![Proxmox](images/proxmox.png)\n\n\n## Bridges and Network interfaces\nWe will create 2 bridges and use the phisical network interface.\n![Bridges](images/bridges.png)\n* **eth0:** Physical interface where we get our public IPv4 and v6 traffic.\n* **vmbr0**: Will be shared to OpenSense as WAN, all the traffic to VMs will go trough here\n* **vmbr1**: Internal IPv4/v6 network, will be shared as LAN with no host IPv4\n\n## Proxmox interface configuration\n```\nauto lo\niface lo inet loopback\n\n# device: eth0\nauto eth0\niface eth0 inet static\n  address xxx.76.28.177\n  netmask 255.255.255.255\n  pointopoint xxx.76.28.161\n  gateway xxx.76.28.161\n\niface eth0 inet6 static\n  address range::2\n  netmask 128\n  gateway fe80::1\n  up sysctl -p\n\n# for single IPs\nauto vmbr0\niface vmbr0 inet static\n  address 169.254.0.1\n  netmask 255.255.0.0\n  bridge_ports none\n  bridge_stp off\n  bridge_fd 0\n  up ip route add 172.16.0.0/16 via 169.254.0.2 dev vmbr0\n\n# WAN Interface in the Firewall VM\niface vmbr0 inet6 static\n  address range::3\n  netmask 128\n  up ip -6 route add range::4 dev vmbr0\n  up ip -6 route add range::/64 via range::4  dev vmbr0\n\n# LAN interface in the Firewall VM\nauto vmbr1\niface vmbr1 inet static\n  address 0.0.0.0\n```\n# Firewall VM (OpnSense)\nWe will need an out of band Firewall to be able to whitelist open ports and for this, we are going to use OpnSense.\n \nMore information here: https://opnsense.org/\n\nWe will add 2 (WAN,LAN) network cards and configure each one to one of the Bridges we created before\n\n![pfSense](images/Proxmox1.png)\n\n## Interfaces assignments in pfSense\n![pfSense](images/pfsense_interfaces2.png)\n### LAN6 (WAN)\nDefault gateways for the VM hosts.\n* IPv6: range::4 /65\n* IPv4: 169.254.0.2 /16\n### LAN\n* IPv4: 172.16.0.1/16 (NATed from Host)\n* IPv6: range:8000::2 /77\n### WireGuard\nWe configure WireGuard in a Site-to-Site setup as described here: https://docs.netgate.com/pfsense/en/latest/recipes/wireguard-s2s.html\n\nWith this configuration:\n\n| Item          | Value                             |\n| ------------- | --------------------------------- |\n| Design        | Site-to-Site, one peer per tunnel |\n| Tunnel Subnet | `fda2:5d88:d5a3:1d4d::/64`        |\n\n\n### Proxmox KVM\n\n| Item           | Value                                                     |\n| -------------- | --------------------------------------------------------- |\n| Endpoint IP Address | `Home IPv4`                                            |\n| TUN IPv6 Address | `fda2:5d88:d5a3:1d4d::1/64`                         |\n| Listen Port    | `51820`                                                   |\n| SatelliteGW | `fda2:5d88:d5a3:1d4d::2` via TUN interface |\n| Static Route| \t`range:8008::/77`\tvia SatelliteGW |\n\n![pfSense](images/pfsense_wireguard.png)\n\n### Home network\n| Item           | Value                                               |\n| -------------- | --------------------------------------------------- |\n| Endpoint IP Address | `Proxmox IPv4`                                         |\n| TUN IPv6 Address | `fda2:5d88:d5a3:1d4d::2/64`     |\n| Listen Port    | `51820`                                             |\n| LAN IPv6     | `range:8008::1/77`  |\n| GW IPv6 | `fda2:5d88:d5a3:1d4d::1/64` via TUN  |\n| DHCPv6 on LAN|  `range:8008:1::` to `range:800f:ffff:ffff:ffff`\n| RA on LAN| Assisted|\n\n![pfSense](images/pfsense_wireguardPeer.png)\n\n### Routing in OPNSense\n\nThe default GW for IPv6 is range::3 trough the WAN interface, this is because this interface is connected to the KVM bridge that has access to the connection to the internet.\n\nEach Docker network in the VM host gets a static route so they can communicate between each other.\n\nFor this we need to define a Gateway  as range:8000:1:0:1 (VM1) trough the LAN interface called \"DockerVM1\" in the picture.\n\nSatelliteGW is the gateway on the other side of the WireGuard Tunnel.\n\n![pfSense bridge](images/pfsense_gateways.png)\n\nFinally we add a 2 static routes:\n* Containers in VM1:  Our container subnet range:8010::/77 can be reached trough the \"DockerVM1\" gateway that means trough the LAN interface via the host at range:8000:1:0:1\n* IPv4 to Ipv6 Tunnel: range:8008::/77 will be served to clients connected to the WireGuard tunnel via the other side of the TUN1 interface at fda2:5d88:d5a3:1d4d::2\n\n![pfSense bridge](images/pfsense_static_routes.png)\n\n\n### Firewall Rules\nThe rules to allow a Port in our IPv6 networks is done in the WAN interface.\n\n![pfSense wan fw](images/pfsense_wan_fw.png)\n\nAllow all IPv4 and IPv6 in the LAN interface\n![pfSense lan fw](images/pfsense_lan_fw.png)\n### LAN DHCPv6\nThis is the VM ipv6 range that will be managed by the DHCP\n* Enable DHCPv6 server with range: range:8000:2:: to range:ffff:ffff:ffff\n* Enable Assisted RA\n* NO dhcpv6 on LAN6(wan)\n\n# Create a Debian template\nFrom https://cloud.debian.org/images/cloud/ Download the latest qcow2 file.\n```\nwget https://cloud.debian.org/images/cloud/bullseye/20230515-1381/debian-11-genericcloud-amd64-20230515-1381.qcow2\nqm create 9500 --name Debian11CloudInit --net0 virtio,bridge=vmbr0\nqm importdisk 9500 debian-11-genericcloud-amd64-20220613-1045.qcow2 local-lvm\nqm set 9500 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-9500-disk-0\nqm set 9500 --ide2 local-lvm:cloudinit\nqm set 9500 --boot c --bootdisk scsi0\nqm set 9500 --serial0 socket --vga serial0\nqm set 9500 --agent enabled=1 #optional but recommended\nqm template 9500\n```\n\n# VM configuration\n* ifconfig\n  \n```\ndocker0: flags=4099\u003cUP,BROADCAST,MULTICAST\u003e  mtu 1500\n        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255\n        inet6 range:8010::1  prefixlen 77  scopeid 0x0\u003cglobal\u003e\n\nens19: flags=4675\u003cUP,BROADCAST,RUNNING,ALLMULTI,MULTICAST\u003e  mtu 1500\n        inet 172.16.99.10  netmask 255.255.0.0  broadcast 172.16.255.255\n        inet6 range:8000:1:0:1  prefixlen 128  scopeid 0x0\u003cglobal\u003e\n```\n* route\n```\n::1 dev lo\nrange:8000:1:0:1 dev ens19 proto kernel metric 100 pref medium\nrange:8000::/77 dev ens19 proto ra metric 100 pref medium\nrange:8008::/77 dev docker0 metric 1024 linkdown pref medium\nrange:8010::/77 dev docker0 proto kernel metric 256 linkdown pref medium\nrange:8010::/77 dev docker0 metric 1024 linkdown pref medium\nfe80::/64 dev ens19 proto kernel metric 100 pref medium\nfe80::/64 dev docker0 proto kernel metric 256 linkdown pref medium\ndefault via fe80::3039:93ff:fe18:ccdd dev ens19 proto ra metric 20100 pref high\n```\n\n\n\n# Docker configuration\nMore information: https://docs.docker.com/v17.09/engine/userguide/networking/default_network/ipv6/#routed-network-environment\n\nWe configure docker to use a /77 subnets under range\n\n* /etc/docker/daemon.json\n```\n{\n  \"ipv6\": true,\n  \"fixed-cidr-v6\": \"range:8010::/77\"\n}\n\n```\nTest it by using an alpine container:\n\n```\n# docker run -it alpine ash\n/ # ip -6 addr\n1: lo: \u003cLOOPBACK,UP,LOWER_UP\u003e mtu 65536 state UNKNOWN qlen 1000\n    inet6 ::1/128 scope host\n       valid_lft forever preferred_lft forever\n11: eth0@if12: \u003cBROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN\u003e mtu 1500 state UP\n    inet6 range:8010:242:ac11:2/77 scope global flags 02\n       valid_lft forever preferred_lft forever\n    inet6 fe80::42:acff:fe11:2/64 scope link\n       valid_lft forever preferred_lft forever\n/ # ip -6 route\nrange:8010::/77 dev eth0  metric 256\nfe80::/64 dev eth0  metric 256\ndefault via range:8010::1 dev eth0  metric 1024\nmulticast ff00::/8 dev eth0  metric 256\n/ # ping -6 www.google.com\nPING www.google.com (2a00:1450:4001:810::2004): 56 data bytes\n64 bytes from 2a00:1450:4001:810::2004: seq=0 ttl=115 time=5.769 ms\n64 bytes from 2a00:1450:4001:810::2004: seq=1 ttl=115 time=5.885 ms\n^C\n--- www.google.com ping statistics ---\n2 packets transmitted, 2 packets received, 0% packet loss\nround-trip min/avg/max = 5.769/5.827/5.885 ms\n\n```\n\nFrom here we can see we got range:ac11:2/77 and ping to Google over IPv6 works.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbruj0%2Fproxmoxipv6","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbruj0%2Fproxmoxipv6","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbruj0%2Fproxmoxipv6/lists"}