After deploying sing-box TUN on Armbian, I encountered a rather counterintuitive issue: IPv6 ping works, but IPv6 HTTPS connections time out after enabling auto_redirect.
The eventual finding was that the problem was not with IPv6 public routing or the proxy node, but rather that the Linux loopback interface lo was missing the ::1/128 address. This article documents the diagnostic process and the fix.
Environment
- Linux: Armbian, ARM64, 6.18-series kernel
- sing-box: 1.14.x
- Network management: Netplan + NetworkManager
- Transparent proxy: TUN,
auto_route: true,auto_redirect: true - IPv6: Automatically configured by the upstream; the interface already has a global IPv6 address and an RA default route
To protect privacy, this article omits the actual public IP addresses, MAC addresses, router address, domain names, and custom internal routing table numbers. The ULA addresses and test targets in the following examples are for demonstration purposes.
Symptoms
Direct IPv6 HTTPS test:
curl --noproxy '*' -6 -v --connect-timeout 5 \
--resolve 'cloudflare.com:443:[2606:4700::6810:85e5]' \
https://cloudflare.com/
After enabling sing-box:
* Trying [2606:4700::6810:85e5]:443...
* Connection timed out after 5002 milliseconds
curl: (28) Connection timed out
Comparison test:
| State | IPv6 HTTPS |
|---|---|
| sing-box stopped | Normal |
auto_redirect: true | Times out |
auto_redirect: false | Normal |
However, a simple ping -6 test may succeed. ICMP connectivity cannot substitute for a TCP/HTTPS test.
Troubleshooting Process
1. Rule Out Issues with the IPv6 Address and Default Route
ip -6 addr show dev eth0 scope global
ip -6 route show default
The interface already has a global IPv6 address, and the default route was learned through RA, in a form such as:
default via fe80::... dev eth0 proto ra
When NetworkManager manages IPv6, whether RA is functioning correctly should not be determined solely from the value of net.ipv6.conf.eth0.accept_ra; the actual addresses and routes must also be observed.
2. Find That TCP Does Not Appear Directly on tun0 or eth0
Observe the HTTPS target through packet capture:
sudo tcpdump -ni tun0 'ip6 and tcp port 443'
sudo tcpdump -ni eth0 'ip6 and tcp port 443'
With auto_redirect enabled, the expected TCP SYN to the target IPv6 address was not observed. This does not necessarily indicate packet loss: sing-box’s nftables rules may first redirect the TCP traffic to a local port.
3. Inspect the Local REDIRECT in nftables
sudo nft -a list table inet sing-box
The rules contain content similar to the following:
meta l4proto tcp ... queue flags bypass to 100
meta l4proto tcp ... redirect to :23457 return
The port shown here is an internal listening port used in this troubleshooting environment; other versions or configurations may use different ports. Check the IPv6 listener:
sudo ss -6 -lntp '( sport = :23457 )'
sing-box is indeed listening on that port.
Continue capturing traffic on the loopback interface:
sudo tcpdump -ni lo -vv 'tcp port 23457'
The key packets observed at this point are similar to the following:
IP6 2001:db8::1234.4210 > ::1.23457: Flags [S]
IP6 2001:db8::1234.4210 > ::1.23457: Flags [S]
IP6 2001:db8::1234.4210 > ::1.23457: Flags [S]
The
2001:db8::/32prefix above is a documentation-only example IPv6 prefix, not an actual public address.
The SYN packets are continually retransmitted without a SYN-ACK, indicating that the connection has been redirected to the local ::1 address, but the local TCP handshake cannot complete.
4. Identify the Root Cause: The Loopback Interface Is Missing an IPv6 Address
ip -6 addr show dev lo
The output is unexpectedly empty. Normally, the loopback interface should have the following:
inet6 ::1/128 scope host
Because ::1/128 is missing, an IPv6 TCP REDIRECT to the local ::1 address cannot establish a connection normally. This matches the repeated SYN packets and the absence of a SYN-ACK.
Fix
First, inspect the IPv6 state of lo:
ip link show lo
sysctl net.ipv6.conf.lo.disable_ipv6
ip -6 addr show dev lo
If IPv6 is disabled:
sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=0
Ensure that the loopback interface is enabled:
sudo ip link set lo up
If ::1/128 still does not appear, add it manually:
sudo ip -6 addr add ::1/128 dev lo
Verify:
ip -6 addr show dev lo
ping -6 -c 2 ::1
curl --noproxy '*' -6 --connect-timeout 5 https://api6.ipify.org
The issue can only be considered resolved after confirming that HTTPS also works when auto_redirect: true.
If the problem occurs after a reboot, check whether /etc/sysctl.d/ contains a configuration that disables IPv6 on lo. You can explicitly set the following in the sysctl configuration file:
net.ipv6.conf.lo.disable_ipv6 = 0
Note that this setting only ensures that IPv6 is not disabled on lo; it does not automatically guarantee that ::1/128 will always exist. If the address disappears again after a reboot, continue investigating the startup order or the service managing lo.
Summary
- A successful IPv6
pingdoes not mean that IPv6 TCP proxying is working; a real HTTPS request must be used for verification. - After enabling sing-box
auto_redirect, some TCP traffic is redirected by nftables to a local port; capturing onlyeth0ortun0may not reveal the expected target traffic. - Confirming the listener with
ssand observing SYN retransmissions withtcpdump -i lowere key to identifying the problem. - The final point of failure was the absence of the IPv6 loopback address
::1/128onlo. - Temporarily disabling
auto_redirectworks around the problem, but fixing the loopback interface is the actual solution for this failure.
Quick Diagnostic Command Reference
ip -6 addr show dev lo
sysctl net.ipv6.conf.lo.disable_ipv6
ip -6 route show default
sudo nft -a list table inet sing-box
sudo ss -6 -lntp '( sport = :23457 )'
sudo tcpdump -ni lo 'tcp port 23457'
Addendum: Downstream Devices Cannot Access the Network After Enabling UFW
After resolving the IPv6 loopback issue, I enabled UFW on Armbian and encountered another phenomenon: the Armbian host itself could access the network normally, but downstream devices connecting through it could not access the network normally.
First, inspect the UFW block logs:
sudo ufw logging medium
sudo journalctl -k -f -o cat | grep --line-buffered 'UFW BLOCK'
The following is a representative sanitized log. The IP addresses use the RFC 5737 documentation example ranges and must not be copied directly into a real network configuration:
[UFW BLOCK] IN=eth0 OUT= SRC=192.0.2.20 DST=192.0.2.254 PROTO=TCP DPT=9091 SYN
[UFW BLOCK] IN=eth0 OUT= SRC=192.0.2.20 DST=192.0.2.254 PROTO=TCP DPT=22703 SYN
Here, OUT= is empty and the destination is a local address, so these requests are classified as INPUT (accessing the Armbian host itself) rather than ordinary FORWARD traffic. The earlier direct suspicion of deny routed was therefore incomplete.
Next, use the following command to identify the listening processes:
sudo ss -lntup | grep -E ':(9091|22703)\b'
The results show that both TCP ports are being listened on by sing-box, with one bound to the LAN IPv4 address and the other bound to the wildcard address. After allowing the corresponding inbound ports, downstream devices regained network access. It is important to emphasize that this demonstrates the relevance of port reachability to the failure, but the listening results alone do not prove that these ports are TUN ports or serve any particular function. The sing-box configuration should be checked to determine their exact purpose.
If a service is intended only for LAN use, UFW can restrict the rule to the actual LAN address and subnet. The following is merely a rule template using the RFC 5737 example subnet; it must be replaced with your actual values:
sudo ufw allow in on eth0 from 192.0.2.0/24 to 192.0.2.254 port 9091 proto tcp
sudo ufw allow in on eth0 from 192.0.2.0/24 to 192.0.2.254 port 22703 proto tcp
Security note: It is not recommended to execute ufw allow 22703/tcp directly without source restrictions. If the port is listening on the wildcard address, particular care should be taken to check whether public IPv6 access has been unintentionally exposed. Nor should all routed traffic be changed to be allowed by default on a long-term basis merely to restore downstream network access.
The key troubleshooting points from this addendum are: first distinguish INPUT from FORWARD using IN / OUT, then confirm the listening process, and finally allow traffic precisely based on its actual source. The UFW status page also cannot replace nft list ruleset, because sing-box’s auto_redirect creates separate nftables rules.