micolous / tollgate

A Python/Django-based Captive Portal System for LAN Parties. (Linux)
http://tollgate.blackhats.net.au/
GNU Affero General Public License v3.0
38 stars 15 forks source link

Nintendo 3DS fails connection test with DNS hijack in place #47

Open micolous opened 11 years ago

micolous commented 11 years ago

In the setup guide, there is a workaround for the Nintendo DS and DSlite which allow them to run behind a captive portal, by feigning the connection test passing.

However, this requires hijacking DNS for this domain.

As a result, it no longer works with the Nintendo 3DS unit. Unknown wether this also affects the Nintendo DSi, or if it is specific versions of the system software.

However, the 3DS web browser operates without running a connection test first, allowing it to connect via captive portal systems only without having that hijack in place.

Need to determine the way that the Nintendo 3DS is determining the success, and find a way to allow both DS and 3DS to work behind captivity.

micolous commented 11 years ago

It appears the connection test does the following:

  1. Looks up conntest.nintendowifi.net.
  2. Retrieves http://conntest.nintendowifi.net with user-agent "CTR AC/02".
  3. If this returns a non-200 error code (OK), fail.
  4. If the IP returning the page is non-Nintendo, fail.
  5. Looks up nncs2.app.nintendowifi.net.
  6. Sends data to nncs2.app.nintendowifi.net on ports 33334 and 10024.
  7. If no response or not correct response, fail.

It seems in order to make the 3DS work, it will require breaking support for DS and DS lite consoles -- unless the official Nintendo server is whitelisted such that it allows unmetered access to the Internet to it's web server. Unsure if this server is being used for anything else (like content distribution), so don't like the idea of unmetering it.

It may be possible to work around this by matching DHCP client hostname and supplying a different DNS server IP that returns a local server for conntest.nintendowifi.net.

Unfortunately that requires running two different nameservers, and complicates the setup.

micolous commented 11 years ago

Only information online about "CTR AC/02" appears to be this page in Japanese: http://doruby.kbmj.com/totoro_blog/20120402/1

It seems to be analysing what data Nintendo 3DS and Playstation Vita are sending to the internet.

micolous commented 11 years ago

TODO:

Find and document all DHCP parameters passed by Nintendo consoles. Appears at the moment that Wii U and Wii both identify with hostname of Wii, and DS and 3DS with Nintendo DS. With full information it may be possible to detect the particular console in use, and send different DNS based on this.

Find if there is a modification that can be made to the conntest page so that it will cause the WiiU and 3DS to detect it as a captive portal, but still passes on the 3DS and WiiU.

sj26 commented 10 years ago

It first looks up conntest.nintendowifi.net, then does a "GET /" with "Host: conntest.nintendowifi.net" and the User-Agent you mention, and expects a 200 response with the "X-Organization: Nintendo" header.

This is an effective nginx config:

server {
  listen 80;
  server_name conntest.nintendowifi.net;
  location / {
    add_header X-Organization Nintendo;
    return 200;
  }
}

It then looks up both nncs1.app.nintendowifi.net, sends 5 packets of 16 NULL bytes to port 10025, then 5 packets of "\x00\x00\x00e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" and 5 packets of "\x00\x00\x00f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" (per python string encoding) to port 33334, then does the same thing to nncs2.app.nintendowifi.net.

Adding a simple script listening on these ports and swallowing packets seems to do the trick. Here's mine (adapted from PlexConnect's DNS server).

micolous commented 10 years ago

Awesome, thanks for that information!

I found that the 3DS actually works fine with a captive portal, however the workarounds for the DS break the 3DS. So if this is a way I can have both working, this is excellent.

That X-Organization: Nintendo header looks like it's new. I don't recall seeing it when I initially developed the workaround for the DS.

Given that the test is run over UDP, dropping the packets to those ports (10025/udp and 33334/udp) when in captivity may be an option, as normally this would return ICMP messages, and wouldn't require a program running to listen on those ports.

Unfortunately, this was very slow moving as I don't have a 3DS myself (only a DS). I'll have to see if I can pick one up second-hand cheaply for testing.