One-click IPv6-over-IPv4 tunnel creation for migrating routed IPv6 prefixes to another host.
This is similar to building your own lightweight "Hurricane Electric Free IPv6 Tunnel Broker".
- Server-side IPv6 tunnels for
sit,gre, andipipon Linux - BSD
gif(4)support for IPv6-over-IPv4 throughsitmode - Strict IPv4 and IPv6 validation
- Automatic public interface and gateway detection with virtual/VPN tunnel filtering
- Persistent IPv6 subnet allocation records and subnet reuse after deletion
- Runtime state under
/var/lib/6in4, logs under/var/log/6in4 - Locking with
flockor a directory lock to prevent concurrent runs - Tunnel MTU and TCP MSS calculation from the underlay interface MTU
- Post-create tunnel diagnostics and optional ping6 health check
- Verified
ndpresponderdownloads with SHA256 checksums on supported Linux architectures - systemd, netplan, systemd-networkd, ifcfg, and BSD persistence templates
- Optional telemetry disable flag and environment variable
| Server | Client |
|---|---|
| One public IPv4 address | One public IPv4 address |
| One globally routed IPv6 prefix | No native IPv6 is required |
| Linux or BSD root shell | Linux root shell for the generated client commands |
The main script installs missing project-level runtime dependencies with the system package manager when possible. Supported package managers include apt, apk, pacman, dnf, yum, zypper, FreeBSD pkg, and OpenBSD pkg_add.
Download:
curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh
chmod +x 6in4.shRun on the IPv6-capable server:
./6in4.sh <client_ipv4> [mode_type] [subnet_size]Examples:
./6in4.sh 203.0.113.10 sit 80
./6in4.sh 203.0.113.10 gre 64 --no-telemetry
./6in4.sh 203.0.113.10 sit 80 --interface eth0 --skip-health-checkOptions:
| Option | Description |
|---|---|
mode_type |
gre, sit, or ipip on Linux. BSD uses sit, implemented with gif(4). Default: sit. |
subnet_size |
IPv6 subnet prefix length, such as 64, 80, or 112. It must be greater than or equal to the server prefix and a multiple of 8. Default: 80. |
--interface <name> |
Force the server public interface. |
--no-telemetry |
Disable the hits counter request. |
--skip-health-check |
Skip the post-create ping6 check. |
--no-persist |
Generate persistence files but do not enable the systemd unit automatically. |
--skip-ndpresponder |
Skip ndpresponder installation/startup. Use only when NDP/proxying is handled another way. |
--dry-run |
Run the allocation/log/persistence flow without root-only network changes. |
Environment:
| Variable | Description |
|---|---|
SIXIN4_STATE_DIR |
Runtime state directory. Default: /var/lib/6in4. |
SIXIN4_LOG_DIR |
Log directory. Default: /var/log/6in4. |
SIXIN4_NO_TELEMETRY=1 |
Same as --no-telemetry. |
SIXIN4_INTERFACE=<name> |
Same as --interface <name>. |
SIXIN4_DRY_RUN=1 |
Same as --dry-run. |
CN=true |
Prefer a reachable GitHub CDN automatically. |
Legacy 6IN4_* names are still accepted when passed with env, for example env 6IN4_STATE_DIR=/tmp/6in4 ./6in4.sh .... The SIXIN4_* aliases are preferred because they can be used directly in POSIX-style shell assignments.
Dry-run test variables:
SIXIN4_OS_FAMILY=linux
SIXIN4_INTERFACE=eth0
SIXIN4_MAIN_IPV4=198.51.100.2
SIXIN4_IPV4_CIDR=198.51.100.2/24
SIXIN4_IPV4_GATEWAY=198.51.100.1
SIXIN4_IPV6_CIDR=2001:470:64::1/64
SIXIN4_IPV6_GATEWAY=fe80::1
SIXIN4_UNDERLAY_MTU=1500Runtime files are kept out of /usr/local/bin:
/var/lib/6in4/allocations.tsv
/var/lib/6in4/subnets_*.list
/var/lib/6in4/persistent/<tunnel_name>/
/var/log/6in4/6in4_server.log
/var/log/6in4/6in4_client.log
Logs rotate automatically when they exceed 1 MiB by default. Override with SIXIN4_LOG_MAX_BYTES and SIXIN4_LOG_KEEP.
After the server tunnel is created, the script prints the client commands and writes them to /var/log/6in4/6in4_client.log. It also generates client persistence templates under:
/var/lib/6in4/persistent/<tunnel_name>/
No passwords or private keys are generated by this project.
Download and run the cleanup script on the server:
curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4-delete.sh -o 6in4-delete.sh
chmod +x 6in4-delete.sh
./6in4-delete.sh --list
./6in4-delete.sh <tunnel_name>Delete every active recorded tunnel:
./6in4-delete.sh --allDeletion removes the kernel tunnel, disables the generated systemd service when present, and marks the allocation record as deleted so the subnet can be reused.
For non-destructive state-flow checks:
SIXIN4_STATE_DIR=/tmp/6in4-dry-run/state ./6in4-delete.sh --dry-run --all--dry-run only previews deletion. It does not remove persistence files or modify allocations.tsv.
On the client:
ip link set user-ipv6 down
ip tunnel del user-ipv6For Linux, the script generates:
server-up.shandserver-down.sh6in4-<tunnel_name>.servicesystemd-networkd-<tunnel_name>.netdevsystemd-networkd-<tunnel_name>.networknetplan-<tunnel_name>.yamlifcfg-<tunnel_name>- client-side shell, systemd, and
client-install.shtemplates
When systemd is available and --no-persist is not used, the server systemd unit is enabled automatically for reboot recovery. Netplan, systemd-networkd, ifcfg, and BSD files are generated as templates because installing them blindly can conflict with existing network managers.
Check the server:
ip addr show
ip -6 route show
systemctl status ndpresponderCheck the client:
ip addr show
curl ipv6.ip.sbThe health check pings the generated client IPv6 address after server creation. It can fail until the client applies its tunnel configuration; the script prints tunnel, address, and route diagnostics in that case.
covert.sh converts /etc/network/interfaces tunnel syntax between ifupdown and ifupdown2. It now backs up the file, validates the converted configuration with ifquery --check --all or ifup --no-act -a, and restores the backup if validation or networking restart fails.