[Bug] `tun.stack=system` On Android 15 (LOS 22.1) Incorrectly Route IPv6 Packages, While `gvisor` Works
Bug Report: tun.stack=system
on Android 15 (LOS 22.1) Incorrectly Routes IPv6 Packages
Introduction
We have encountered a bug on Android 15 (LOS 22.1) where setting tun.stack
to system
or mixed
causes IPv6 packages to be incorrectly routed. This issue is not present when using gvisor
as the tun.stack
value. In this article, we will provide a detailed description of the problem, the steps to reproduce it, and the relevant logs.
Description
When tun.stack
is set to system
or mixed
and the destination address is an IPv6 address, applications are unable to connect to the outside network. The curl
command raises a "cannot connect to server" error, without any indication of a routing issue or network unreachability. This problem occurs even though the ip addr
command shows that IPv6 addresses are configured, and the mtr
command indicates that the utun
interface is selected with an fdfe
prefix.
Steps to Reproduce
- Set up the configuration file with the necessary proxies (which should work without IPv6).
- Set
tun.stack
tosystem
ormixed
. - Attempt to connect to an IPv6 network using
curl
or another application. For example, try connecting to the IPv6-only domaintest6.ustc.edu.cn
.
Logs
The relevant log is attached as a GitHub file. The log shows that the curl
command fails to connect to the server, with a "cannot connect to server" error.
Reproduction Method
- Set up the configuration file with the necessary proxies (which should work without IPv6).
- Set
tun.stack
tosystem
ormixed
. - Try connecting to an IPv6 network using
curl
or another application.
Configuration File
The configuration file used to reproduce this issue is provided below:
log-level: debug
# redir-port: 9797
# tproxy-port: 9898
mixed-port: 7890
# unified-delay: true
geo-auto-update: true
geo-update-interval: 24
geodata-mode: true
keep-alive-interval: 90
tcp-concurrent: true
enable-process: true
find-process-mode: always
mode: rule
allow-lan: true
bind-address: '*'
external-controller: 0.0.0.0:9090
external-secret: ''
external-ui: './dashboard'
# do health check in proxy (group), deprecate this
# hp: &hp {interval: 10800, health-check: {enable: true, url: https://www.gstatic.com/generate_204, interval: 300}}
# hp-gh: &hp-gh {interval: 10800, health-check: {enable: true, url: https://raw.githubusercontent.com, expected-status: 301, interval: 300}}
profile:
store-selected: true
# 储存 API 对策略组的选择,以供下次启动时使用
store-fake-ip: false
# 储存 fakeip 映射表,域名再次发生连接时,使用原有映射地址
sniffer:
enable: true
force-dns-mapping: true
sniff: # TLS 默认如果不配置 ports 默认嗅探 443
TLS:
ports: [443, 8443]
HTTP: # 需要嗅探的端口, 默认嗅探 80
ports: [80, 8080-8880]
force-domain:
- '+.v2ex.com'
# 白名单,跳过嗅探结果
skip-domain:
- 'Mijia Cloud'
- '+.cn'
- 'geosite:private'
tun:
enable: true
mtu: 9000
device: utun
stack: system # gvisor / system / lwip
dns-hijack:
- 'any:53'
- 'tcp://any:53'
auto-route: true
# strict-route: true
auto-detect-interface: true
include-android-user: [0, 10]
exclude-package:
- 'com.android.captiveportallogin'
- 'com.xingin.xhs'
- 'com.UCMobile'
- 'org.localsend.localsend_app'
# blacklist
include-package: [] # whitelist
dns:
enable: true
listen: ':1053'
ipv6: true
enhanced-mode: 'redir-host'
use-hosts: true
hosts:
'yasho.ku':
'x.com'
'dns.alidns.com':
- '223.5.5.5'
- '223.6.6.6'
- '2400:3200::1'
- '2400:3200:baba::1'
'dns.google':
- '8.8.8.8'
- '8.8.4.4'
- '2001:4860:4860::8888'
- '2001:4860:4860::8844'
'one.one.one.one':
- '1.1.1.1'
- '1.0.0.1' # mihomo does not support shorten fqdn
- '2606:4700:4700::1111'
- '2606:4700:4700::1001'
# looks like gfw would detect gfwlist query even doh
# do redir-host through proxy to eliminate leaking
prefer-h3: false
nameserver:
- 'https://dns.google/dns-query#🕸️ GFWList'
- 'https://one.one.one.one/dns-query#🕸️ GFWList'
- 'https://dns.google/dns-query'
- 'https://one.one.one.one/dns-query'
nameserver-policy:
'geosite:cn':
- 'https://dns.alidns.com/dns-query'
- 'tls://dot.pub'
- '180.76.76.76'
'geosite:private':
- 'system'
proxy-providers:
sub:
interval: 10800
type: http
url: ""
path: "./proxy-provider/sub.yml"
override:
dialer-proxy: "🏄 免流"
bdml:
type: file
path: "./proxy-provider/bdbox51.yaml"
aliml:
type: file
path: "./proxy-provider/gwalicdn.yaml"
proxy-groups:
-
name: "🎛 代理编组"
type: select
proxies: ["💫 Fail Auto Switch", "AUTO"]
-
name: "💫 Fail Auto Switch"
type: fallback
include-all-proxies: true
use: ["neko-service", "prprcloud"]
exclude-filter: "流量|套餐|重置"
-
name: "🏄 免流"
type: select
proxies:
- DIRECT
- "bd"
- "ali"
-
name: "bd"
type: select
use:
- "bdml"
url: https://connect.rom.miui.com/generate_204
-
name: "ali"
type: select
use:
- "aliml"
url: https://connect.rom.miui.com/generate_204
-
name: "🔮 ANY OTHERS"
type: select
proxies: ["🎛 代理编组", 'DIRECT', 'REJECT']
-
name: "🕸️ GFWList"
type: select
proxies: ["🎛 代理编组", 'DIRECT', 'REJECT']
-
name: "🥮 大陆网域"
type: select
proxies: ["🏄 免流", "🎛 代理编组", 'REJECT']
-
name: "🍎 Apple 中国"
type: select
proxies: ["🔮 ANY OTHERS", "🕸️ GFWList", "🥮 大陆网域"]
-
name: "🍏 Apple iCloud"
type: select
proxies: ["🔮 ANY OTHERS", "🕸️ GFWList", "🥮 大陆网域"]
-
name: "🍥 Google 中国 (慎用)"
type: select
proxies: ["🕸️ GFWList", "🥮 大陆网域", "🔮 ANY OTHERS", 'REJECT']
-
name: "💺 Microsoft 中国"
type: select
proxies: ["🕸️ GFWList", "🥮 大陆网域", "🔮 ANY OTHERS", 'REJECT']
-
name: "💬 Telegram"
type: select
proxies: ["🕸️ GFWList", "🥮 大陆网域", "🔮 ANY OTHERS"]
-
name: "🖥️ 本地网络"
type: select
proxies: ['DIRECT', "<br/>
**Q&A: `tun.stack=system` on Android 15 (LOS 22.1) Incorrectly Routes IPv6 Packages**
**Q: What is the issue with `tun.stack=system` on Android 15 (LOS 22.1)?**
A: The issue is that when `tun.stack` is set to `system` or `mixed` and the destination address is an IPv6 address, applications are unable to connect to the outside network. This is because the IPv6 packets are being incorrectly routed.
**Q: What happens when I try to connect to an IPv6 network using `curl` or another application?**
A: When you try to connect to an IPv6 network using `curl` or another application, you will receive a "cannot connect to server" error. This is because the IPv6 packets are not being routed correctly.
**Q: Why is this issue only happening on Android 15 (LOS 22.1)?**
A: This issue is specific to Android 15 (LOS 22.1) and is not present on other versions of Android or on Windows 11 Home.
**Q: What is the difference between `tun.stack=system` and `tun.stack=gvisor`?**
A: When `tun.stack` is set to `gvisor`, the IPv6 packets are routed correctly and applications are able to connect to the outside network. However, when `tun.stack` is set to `system` or `mixed`, the IPv6 packets are incorrectly routed and applications are unable to connect to the outside network.
**Q: How can I reproduce this issue?**
A: To reproduce this issue, you can follow these steps:
1. Set up the configuration file with the necessary proxies (which should work without IPv6).
2. Set `tun.stack` to `system` or `mixed`.
3. Try connecting to an IPv6 network using `curl` or another application.
**Q: What are the relevant logs for this issue?**
A: The relevant logs for this issue are attached as a GitHub file. The log shows that the `curl` command fails to connect to the server, with a "cannot connect to server" error.
**Q: How can I fix this issue?**
A: To fix this issue, you can set `tun.stack` to `gvisor` instead of `system` or `mixed`. This will ensure that the IPv6 packets are routed correctly and applications are able to connect to the outside network.
**Q: Is there a workaround for this issue?**
A: Yes, there is a workaround for this issue. You can use a VPN or a proxy server to route your IPv6 traffic through a different network. This will allow you to connect to IPv6 networks even when `tun.stack` is set to `system` or `mixed`.
**Q: Will this issue be fixed in future versions of Android?**
A: We are working to fix this issue in future versions of Android. In the meantime, you can use the workaround mentioned above or set `tun.stack` to `gvisor` to ensure that your IPv6 traffic is routed correctly.