AlwaysOnline is a HTTP and DNS server which mocks a lot network/internet/portal detection servers.
Ports required: tcp/80, tcp/53, udp/53.
Start the server:
```shell script
docker run \ -d --restart unless-stopped \ --cap-drop ALL --cap-add NET_BIND_SERVICE \ -p 80:80 -p 53:53 -p 53:53/udp \ jamesits/alwaysonline:latest --ipv4 192.168.1.2 --ipv6 fd00::2
chmod +x ./alwaysonline setcap cap_net_bind_service=+ep ./alwaysonline ./alwaysonline --ipv4 192.168.1.2 --ipv6 fd00::2
(Pass the IP address end users use to connect to the server. See [Which IP Address Should I Use](#which-ip-address-should-i-use) for more information.)
Hijack (delegate) the following domains (including subdomains) on your DNS server to the AlwaysOnline server IP address (and disable DNSSEC verification if possible):
// Windows msftncsi.com msftconnecttest.com resolver1.opendns.com (if you use WindowsSpyBlocker to change NCSI config)
// iOS, macOS captive.apple.com
// Android clients3.google.com connectivitycheck.gstatic.com connectivitycheck.android.com connect.rom.miui.com connectivitycheck.platform.hicloud.com // www.googleapis.cn (for MCC=460 sim cards only; might impact other services; not recommended; see https://cs.android.com/android/platform/superproject/+/master:packages/modules/NetworkStack/res/values-mcc460/config.xml?q=values-mcc460)
// Linux network-test.debian.org nmcheck.gnome.org www.archlinux.org (DO NOT hijack archlinux.org or other subdomains) capnet.elementary.io
# Development
## Building
```shell
goreleaser build --snapshot --clean --single-target
Microsoft Store refuses to work when NCSI reports "no Internet", even if it can load everything. Also some UWP games (e.g. ones authorized by Xbox Game Pass) refuse to work without a "Internet". But NCSI is so unreliable in my area that 99% of the time I have the disconnected globe icon on my taskbar. This is why I wrote this piece of software in the first place.
By terminating portal detection servers in your LAN, you also benefit from:
Whatever IP addresses you pass to the 2 parameters
--ipv4--ipv6will be sent to the client in every DNS response, so that the following HTTP requests will come back to the IP addresses you specified. Generally speaking:
The server will always listen on 0.0.0.0/[::] regardless of the IP addresses you specified.
It is possible to use only the HTTP server provided by AlwaysOnline. Just make sure you fake every DNS responses right on your own DNS server.
AlwaysOnline need cap_net_bind_service=+ep to listen on ports 53 and 80 as a non-root user. It is recommended to run AlwaysOnline in a confined, readonly environment.
Exposing AlwaysOnline directly to the internet is not recommended, mainly because DNS/UDP can passively anticipate in an amplification/reflection DDoS attack. AlwaysOnline does not implement any rate limiting or abnormal client blocking mechanism.
AlwaysOnline is stateless, so it is possible to run multiple instances to accommodate your high availability needs. Failover is realized by a 1-second DNS cache TTL and your own DNS server's failover capability.
I acknowledge this is not the best way to implement HA, but it is simple and enough for casual deployments. If you use AlwaysOnline in a mission-critical environment, then external load balancer with upstream health check (e.g. Nginx or HAProxy) and/or distributed container orchestration tools (e.g. Docker Swarm Mode or Kubernetes) are strongly recommended.
AlwaysOnline replies to any URL segments it recognizes, regardless of which domain it comes from. If your client speaks a protocol AlwaysOnline implements but on a different domain, simply add another delegation on your DNS server and everything should work.
Service NlaSvc controls NCSI -- Network Connectivity Status Indicator, i.e. the tray icon on your taskbar showing whether you have Internet access. The service, when it goes wrong, is very annoying, as it will cause Microsoft Store to be unusable and all your UWP games unplayable even if you actually have Internet access.
NCSI use a set of DNS and HTTP tests to detect if the device is connected to the Internet. The tests can be customized at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet. AlwaysOnline implements the default config. (BTW, Windows 10 CMGE have the same NCSI config as every other Windows 10. )
For a network to trigger the NCSI tests, you need an address, network mask and DNS server to be set. For IPv6 networks, the IP address need to be a global one (in the range 2000::/3). Sometimes you need a default gateway, but not always.

NCSI will cache negative results for a network, so if a network is detected to be non-Internet, NCSI will not test it for a long period, even if the network adapter is disabled then re-enabled.
If you don't want to deploy a server or you don't have a suitable LAN environment, NCSIOverride can be used to fake NCSI results on a single machine.
Stock Android 7.1.1 or later will connect to both HTTP and HTTPS endpoints for internet detection. AlwaysOnline does not implement the HTTPS server due to obvious reasons.
If you have privacy concerns, you can change the endpoint URLs manually with ADB. See: https://www.noisyfox.io/android-captive-portal.html
$ claude mcp add alwaysonline \
-- python -m otcore.mcp_server <graph>