Describe the bug
IPv6 packets to a container's *.orb.local address are silently dropped when they
are larger than 1280 bytes (the IPv6 minimum MTU). No ICMPv6 "Packet Too Big" is
sent back, and both the interface and the route keep reporting MTU 1500. IPv4 to
the very same container works fine with a 1500-byte packet and DF set.
Because *.orb.local resolves to an A and an AAAA record, clients often pick
IPv6. Small replies arrive, so the TCP connection comes up and looks healthy —
but any response larger than ~1280 bytes stalls until the client times out. curl
then reports a valid HTTP status with an incomplete body:
$ curl -sS -o /dev/null -w 'code=%{http_code} exit=%{exitcode} ip=%{remote_ip} size=%{size_download}\n' \
--max-time 10 http://my-app.k8s.orb.local/
code=200 exit=28 ip=fd07:b51a:cc66:0:a617:db5e:c0a8:8a03 size=0
curl: (28) Operation timed out after 10002 ms with 0 out of 63166 bytes received
$ curl -sS -o /dev/null -w 'code=%{http_code} exit=%{exitcode} ip=%{remote_ip} size=%{size_download}\n' \
-H 'Host: my-app.k8s.orb.local' http://192.168.138.3/
code=200 exit=0 ip=192.168.138.3 size=63166 # same page over IPv4: 27 ms
Which address family a client picks is not deterministic. In one series the same
URL went over IPv6 five times in a row (all broken), then over IPv4 three times
(all fine), so containers appear to fail at random. Happy Eyeballs does not help,
because the connect succeeds — only the data transfer stalls. Safari recovers
(it retries over IPv4), Chrome stays on the broken socket and the page never
finishes loading.
To Reproduce
# 1. Start any container that just stays alive
docker run -d --rm --name mtu-probe --entrypoint sh alpine -c 'sleep 300'
# 2. Look up both addresses
dscacheutil -q host -a name mtu-probe.orb.local
# ip_address: 192.168.138.173
# ipv6_address: fd07:b51a:cc66:0:a617:db5e:c0a8:8aad
# 3. IPv6 at exactly the minimum MTU -> works (1232 + 48 = 1280 bytes)
ping6 -c1 -s 1232 fd07:b51a:cc66:0:a617:db5e:c0a8:8aad # reply
# 4. One byte more -> no reply, and no ICMPv6 Packet Too Big
ping6 -c1 -s 1233 fd07:b51a:cc66:0:a617:db5e:c0a8:8aad # silent timeout
ping6 -c1 -s 1300 fd07:b51a:cc66:0:a617:db5e:c0a8:8aad # silent timeout
# 5. IPv4 to the same container, 1500 bytes with DF -> works
ping -D -c1 -s 1472 192.168.138.173 # reply
For the HTTP symptom, serve any page larger than ~1280 bytes from the container
and fetch it over the IPv6 address with a Host header.
What I already narrowed down
- Not Kubernetes-specific. I first hit this through
<ns>.k8s.orb.local
behind an ingress controller, but a plain Docker container shows exactly the
same 1280-byte cliff.
- The bridge itself is fine.
ping6 -s 1300 to the OrbStack gateway
(fd07:b51a:cc66::1) and to the Mac's own bridge100 address
(fd07:b51a:cc66:0:a617:db5e:ab7:e9f1) both get replies. Only the
per-container ULA is capped.
- The container ULA embeds its IPv4 address:
…:c0a8:8aad = 192.168.138.173.
- The container has no global IPv6 address inside the VM.
ip -6 addr show scope global in the container is empty, so the ULA looks
like a host-side mapping rather than an address configured in the guest.
- Nothing advertises a smaller MTU.
ndp -i bridge100 reports
linkmtu=1500, ifconfig bridge100 reports mtu 1500, and
route -n get -inet6 <ula> still reports mtu 1500 after the failed pings —
so no Packet Too Big is arriving.
- IPv6 is not disabled in my configuration.
network.subnet4 is
192.168.138.0/23; I could not find an IPv6 switch in orb config.
- Occasionally a few bytes do get through before the stall (I have seen curl
receive 3830 of 63166 bytes, and also 0 of 63166), so it is not a hard block
on the connection.
Possibly related but not the same: #1790 (closed, milestone v2.2.0) was about
an AAAA being resolved inside containers while IPv6 was disabled. Here the AAAA
resolves and connects fine — it just cannot carry more than 1280 bytes. I am on
2.2.1, so after that fix.
Expected behavior
Either IPv6 carries packets up to the link MTU (1500) like IPv4 does, or OrbStack
replies with ICMPv6 Packet Too Big so the client can lower its path MTU. Dropping
packets silently while the interface and route still advertise MTU 1500 leaves
clients hanging until they time out, and makes containers look randomly broken
depending on which address family the client happened to pick.
Diagnostic report
OrbStack info:
Version: 2.2.1
Commit: 0e182b501fcd9e05b99ffb363fce03610390c400 (v2.2.1)
System info:
macOS: 26.5.2 (25F84)
CPU: arm64, 12 cores
CPU model: Apple M2 Max
Model: Mac14,5
Memory: 32 GiB
Full report: https://orbstack.dev/_admin/diag/orbstack-diagreport_2026-07-29T16-44-12.892423Z.zip
Screenshots and additional context
network.subnet4: 192.168.138.0/23, network_bridge: true, k8s.enable: true
docker.expose_ports_to_lan: true, k8s.expose_services: false
- No IPv6 setting found in
orb config on 2.2.1.
A practical note for others hitting this: forcing IPv4 (curl -4, or connecting
to the container's IPv4 address with a Host header) works around it, but
browsers and other clients still pick IPv6 on their own.
Describe the bug
IPv6 packets to a container's
*.orb.localaddress are silently dropped when theyare larger than 1280 bytes (the IPv6 minimum MTU). No ICMPv6 "Packet Too Big" is
sent back, and both the interface and the route keep reporting MTU 1500. IPv4 to
the very same container works fine with a 1500-byte packet and DF set.
Because
*.orb.localresolves to an A and an AAAA record, clients often pickIPv6. Small replies arrive, so the TCP connection comes up and looks healthy —
but any response larger than ~1280 bytes stalls until the client times out. curl
then reports a valid HTTP status with an incomplete body:
Which address family a client picks is not deterministic. In one series the same
URL went over IPv6 five times in a row (all broken), then over IPv4 three times
(all fine), so containers appear to fail at random. Happy Eyeballs does not help,
because the connect succeeds — only the data transfer stalls. Safari recovers
(it retries over IPv4), Chrome stays on the broken socket and the page never
finishes loading.
To Reproduce
For the HTTP symptom, serve any page larger than ~1280 bytes from the container
and fetch it over the IPv6 address with a
Hostheader.What I already narrowed down
<ns>.k8s.orb.localbehind an ingress controller, but a plain Docker container shows exactly the
same 1280-byte cliff.
ping6 -s 1300to the OrbStack gateway(
fd07:b51a:cc66::1) and to the Mac's ownbridge100address(
fd07:b51a:cc66:0:a617:db5e:ab7:e9f1) both get replies. Only theper-container ULA is capped.
…:c0a8:8aad=192.168.138.173.ip -6 addr show scope globalin the container is empty, so the ULA lookslike a host-side mapping rather than an address configured in the guest.
ndp -i bridge100reportslinkmtu=1500,ifconfig bridge100reportsmtu 1500, androute -n get -inet6 <ula>still reportsmtu 1500after the failed pings —so no Packet Too Big is arriving.
network.subnet4is192.168.138.0/23; I could not find an IPv6 switch inorb config.receive 3830 of 63166 bytes, and also 0 of 63166), so it is not a hard block
on the connection.
Possibly related but not the same: #1790 (closed, milestone v2.2.0) was about
an AAAA being resolved inside containers while IPv6 was disabled. Here the AAAA
resolves and connects fine — it just cannot carry more than 1280 bytes. I am on
2.2.1, so after that fix.
Expected behavior
Either IPv6 carries packets up to the link MTU (1500) like IPv4 does, or OrbStack
replies with ICMPv6 Packet Too Big so the client can lower its path MTU. Dropping
packets silently while the interface and route still advertise MTU 1500 leaves
clients hanging until they time out, and makes containers look randomly broken
depending on which address family the client happened to pick.
Diagnostic report
Screenshots and additional context
network.subnet4: 192.168.138.0/23,network_bridge: true,k8s.enable: truedocker.expose_ports_to_lan: true,k8s.expose_services: falseorb configon 2.2.1.A practical note for others hitting this: forcing IPv4 (
curl -4, or connectingto the container's IPv4 address with a
Hostheader) works around it, butbrowsers and other clients still pick IPv6 on their own.