From bfcf28dc3120f2cf2ef12555efbf35932b1f1af4 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Mon, 30 Aug 2021 16:21:08 -0400 Subject: [PATCH 01/74] Add issues that I experienced into the readme This adds some issues that I faced into the "Known Issues" section of the readme. The solution for the client certificate failure is from the readme of superwhiskers/mitmproxy-nintendo, but it was removed in the Pretendo fork. --- readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 861f2fe..13bc756 100644 --- a/readme.md +++ b/readme.md @@ -18,4 +18,6 @@ For use with Pretendo run with the option `--scripts ./pretendo_addon.py`. This ## Known issues -- WiiU eShop does not work (crashes on boot) \ No newline at end of file +- WiiU eShop does not work (crashes on boot) +- Occasionally, a site will not work and cause a certificate warning in the mitmproxy logs. If this happens, go into the client-certificate directory of this repository and create a symbolic link to ctr-common-1.pem if you are using a 3DS or WIIU_COMMON_CERT_1.pem if you are using a Wii U named .pem and try again. +- It is not possible to use SSLv3 or SSLv2 using the latest version of mitmproxy with OpenSSL. This might cause problems with certain servers. There is currently no workaround for this because OpenSSL 1.1.x has completely removed support for old versions of SSL. From 267506f05959e98b09874ce7b0aad6c17ceeaaa0 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Mon, 30 Aug 2021 17:03:04 -0400 Subject: [PATCH 02/74] Update and simplify gitignore --- .gitignore | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 03866ab..d12df34 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,6 @@ -# .gitignore +# Files generated by mitmproxy but not the configuration +configuration/* +!configuration/config.yaml -# mitmproxy certs -mitmproxy-ca-cert.p12 -mitmproxy-ca.p12 -mitmproxy-dhparam.pem -mitmproxy-ca-cert.cer -mitmproxy-ca-cert.pem -mitmproxy-ca.pem - -# python +# Python cache __pycache__ \ No newline at end of file From da9cd28a9221ff306d51192b0213dad8e438638b Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Mon, 30 Aug 2021 17:07:21 -0400 Subject: [PATCH 03/74] Update and simplify the config file This greatly simplifies the config.yaml file by removing unnecessary default settings. It also contains some of my settings for convenience, some issue workarounds, and comments that better explain the purpose of each setting. --- configuration/config.yaml | 315 ++++---------------------------------- 1 file changed, 27 insertions(+), 288 deletions(-) diff --git a/configuration/config.yaml b/configuration/config.yaml index ebef0d6..82805b0 100644 --- a/configuration/config.yaml +++ b/configuration/config.yaml @@ -1,292 +1,31 @@ +# See https://docs.mitmproxy.org/stable/concepts-options/ for documentation -# Add all certificates of the upstream server to the certificate chain -# that will be served to the proxy client, as extras. Type bool. -add_upstream_certs_to_client_chain: false +# An easy-to-remember port that should not conflict with anything +listen_port: 2240 +web_port: 8088 -# Opposite of --ignore-hosts. Type sequence of str. -allow_hosts: [] - -# Strip out request headers that might cause the server to return -# 304-not-modified. Type bool. -anticache: false - -# Try to convince servers to send us un-compressed data. Type bool. -anticomp: false - -# Block connections from globally reachable networks, as defined in the -# IANA special purpose registries. Type bool. -block_global: true - -# Block connections from private networks, as defined in the IANA -# special purpose registries. This option does not affect loopback -# addresses. Type bool. -block_private: false - -# Byte size limit of HTTP request and response bodies. Understands k/m/g -# suffixes, i.e. 3m for 3 megabytes. Type optional str. -body_size_limit: - -# SSL certificates of the form "[domain=]path". The domain may include a -# wildcard, and is equal to "*" if not specified. The file at path is a -# certificate in PEM format. If a private key is included in the PEM, it -# is used, else the default key in the conf dir is used. The PEM file -# should contain the full certificate chain, with the leaf certificate -# as the first entry. Type sequence of str. -certs: [] - -# Set supported ciphers for client connections using OpenSSL syntax. -# Type optional str. -ciphers_client: - -# Set supported ciphers for server connections using OpenSSL syntax. -# Type optional str. -ciphers_server: - -# Client certificate file or directory. Type optional str. -client_certs: "./client-certificates" - -# Replay client requests from a saved file. Type sequence of str. -client_replay: [] - -# Persist command history between mitmproxy invocations. Type bool. -command_history: true - -# Location of the default mitmproxy configuration files. Type str. -confdir: ./confdir - -# The default content view mode. Valid values are 'auto', 'raw', 'hex', -# 'json', 'xml/html', 'wbxml', 'javascript', 'css', 'url-encoded', -# 'multipart form', 'image', 'query', 'protocol buffer'. -console_default_contentview: auto - -# EventLog verbosity. Valid values are 'error', 'warn', 'info', 'alert', -# 'debug'. -console_eventlog_verbosity: info - -# Set the flowlist layout Valid values are 'default', 'list', 'table'. -console_flowlist_layout: default - -# Focus follows new flows. Type bool. -console_focus_follow: false - -# Console layout. Valid values are 'horizontal', 'single', 'vertical'. -console_layout: single - -# Show layout component headers Type bool. -console_layout_headers: true - -# Console mouse interaction. Type bool. -console_mouse: true - -# Color palette. Valid values are 'dark', 'light', 'lowdark', -# 'lowlight', 'solarized_dark', 'solarized_light'. -console_palette: solarized_dark - -# Set transparent background for palette. Type bool. -console_palette_transparent: false - -# Flow content view lines limit. Limit is enabled by default to speedup -# flows browsing. Type int. -content_view_lines_cutoff: 512 - -# Enable/disable HTTP/2 support. HTTP/2 support is enabled by default. -# Type bool. -http2: true - -# PRIORITY forwarding for HTTP/2 connections. Disabled by default to -# ensure compatibility with misbehaving servers. Type bool. -http2_priority: false - -# Ignore host and forward all traffic without processing it. In -# transparent mode, it is recommended to use an IP address (range), not -# the hostname. In regular mode, only SSL traffic is ignored and the -# hostname should be used. The supplied value is interpreted as a -# regular expression and matched on the ip or the hostname. Type -# sequence of str. -ignore_hosts: [] - -# Intercept filter expression. Type optional str. -intercept: - -# Intercept toggle Type bool. -intercept_active: false - -# Reverse Proxy: Keep the original host header instead of rewriting it -# to the reverse proxy target. Type bool. -keep_host_header: false - -# TLS key size for certificates and CA. Type int. -key_size: 2048 - -# Address to bind proxy to. Type str. -listen_host: '' - -# Proxy service port. Type int. -listen_port: 8080 - -# Mode can be "regular", "transparent", "socks5", "reverse:SPEC", or -# "upstream:SPEC". For reverse and upstream proxy modes, SPEC is host -# specification in the form of "http[s]://host[:port]". Type str. -mode: regular - -# Toggle the mitmproxy onboarding app. Type bool. -onboarding: true - -# Onboarding app domain. For transparent mode, use an IP when a DNS -# entry for the app domain is not present. Type str. -onboarding_host: mitm.it - -# Port to serve the onboarding app from. Type int. -onboarding_port: 80 - -# Require proxy authentication. Format: "username:pass", "any" to accept -# any user/pass combination, "@path" to use an Apache htpasswd file, or -# "ldap[s]:url_server_ldap:dn_auth:password:dn_subtree" for LDAP -# authentication. Type optional str. -proxyauth: - -# Enable/disable experimental raw TCP support. TCP connections starting -# with non-ascii bytes are treated as if they would match tcp_hosts. The -# heuristic is very rough, use with caution. Disabled by default. Type -# bool. -rawtcp: false - -# Read only matching flows. Type optional str. -readfile_filter: - -# Replacement patterns of the form "/pattern/regex/replacement", where -# the separator can be any character. Type sequence of str. -replacements: [] - -# Read flows from file. Type optional str. -rfile: - -# Stream flows to file as they arrive. Prefix path with + to append. -# Type optional str. -save_stream_file: - -# Filter which flows are written to file. Type optional str. -save_stream_filter: - -# Execute a script. Type sequence of str. -scripts: [] - -# Start a proxy server. Enabled by default. Type bool. -server: true - -# Replay server responses from a saved file. Type sequence of str. -server_replay: [] - -# Ignore request's content while searching for a saved flow to replay. -# Type bool. -server_replay_ignore_content: false - -# Ignore request's destination host while searching for a saved flow to -# replay. Type bool. -server_replay_ignore_host: false - -# Request's parameters to be ignored while searching for a saved flow to -# replay. Type sequence of str. -server_replay_ignore_params: [] - -# Request's payload parameters (application/x-www-form-urlencoded or -# multipart/form-data) to be ignored while searching for a saved flow to -# replay. Type sequence of str. -server_replay_ignore_payload_params: [] - -# Ignore request's destination port while searching for a saved flow to -# replay. Type bool. -server_replay_ignore_port: false - -# Kill extra requests during replay. Type bool. -server_replay_kill_extra: false - -# Don't remove flows from server replay state after use. This makes it -# possible to replay same response multiple times. Type bool. -server_replay_nopop: false - -# Refresh server replay responses by adjusting date, expires and last- -# modified headers, as well as adjusting cookie expiration. Type bool. -server_replay_refresh: true - -# Request headers to be considered during replay. Type sequence of str. -server_replay_use_headers: [] - -# Header set pattern of the form "/pattern/header/value", where the -# separator can be any character. Type sequence of str. -setheaders: [] - -# Use the Host header to construct URLs for display. Type bool. -showhost: false - -# Use the client's IP for server-side connections. Combine with -# --upstream-bind-address to spoof a fixed source address. Type bool. -spoof_source_address: false - -# Do not verify upstream server SSL/TLS certificates. Type bool. +# These settings make sure that connections are not blocked because they use an old version of TLS. This was probably the most annoying problem to solve for me. +# Note that not all of these settings are actually used; some are just for compatability with older versions and are ignored. ssl_insecure: true - -# Path to a PEM formatted trusted CA certificate. Type optional str. -ssl_verify_upstream_trusted_ca: - -# Path to a directory of trusted CA certificates for upstream server -# verification prepared using the c_rehash tool. Type optional str. -ssl_verify_upstream_trusted_confdir: - -# Set supported SSL/TLS versions for client connections. SSLv2, SSLv3 -# and 'all' are INSECURE. Defaults to secure, which is TLS1.0+. Valid -# values are 'all', 'secure', 'SSLv2', 'SSLv3', 'TLSv1', 'TLSv1_1', -# 'TLSv1_2'. -ssl_version_client: secure - -# Set supported SSL/TLS versions for server connections. SSLv2, SSLv3 -# and 'all' are INSECURE. Defaults to secure, which is TLS1.0+. Valid -# values are 'all', 'secure', 'SSLv2', 'SSLv3', 'TLSv1', 'TLSv1_1', -# 'TLSv1_2'. -ssl_version_server: secure - -# Set sticky auth filter. Matched against requests. Type optional str. -stickyauth: - -# Set sticky cookie filter. Matched against requests. Type optional str. -stickycookie: - -# Stream data to the client if response body exceeds the given -# threshold. If streamed, the body will not be stored in any way. -# Understands k/m/g suffixes, i.e. 3m for 3 megabytes. Type optional -# str. -stream_large_bodies: - -# Stream WebSocket messages between client and server. Messages are -# captured and cannot be modified. Type bool. -stream_websockets: false - -# Generic TCP SSL proxy mode for all hosts that match the pattern. -# Similar to --ignore, but SSL connections are intercepted. The -# communication contents are printed to the log in verbose mode. Type -# sequence of str. -tcp_hosts: [] - -# Add HTTP Basic authentication to upstream proxy and reverse proxy -# requests. Format: username:password. Type optional str. -upstream_auth: - -# Address to bind upstream requests to. Type str. -upstream_bind_address: '' - -# Connect to upstream server to look up certificate details. Type bool. upstream_cert: false - -# Limit the view to matching flows. Type optional str. -view_filter: - -# Flow sort order. Valid values are 'time', 'method', 'url', 'size'. -view_order: time - -# Reverse the sorting order. Type bool. -view_order_reversed: false - -# Enable/disable WebSocket support. WebSocket support is enabled by -# default. Type bool. -websocket: true - +tls_version_server_min: UNBOUNDED +tls_version_client_min: UNBOUNDED +ssl_version_server: all +ssl_version_client: all +ciphers_client: all +ciphers_server: all + +# These just make sure that the right configuration files and certificates are loaded. +client_certs: ./client-certificates +confdir: ./configuration + +# This enables the Pretendo redirection script. +scripts: ./pretendo_addon.py + +# This simply attempts makes sure that no requests are cached. +anticache: true + +# Just convenience features +console_focus_follow: true +showhost: true +console_palette: dark \ No newline at end of file From cb4067e55af90a7bce52efd76c703003a2d87312 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Mon, 30 Aug 2021 19:15:17 -0400 Subject: [PATCH 04/74] Reformat the configuration file --- configuration/config.yaml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/configuration/config.yaml b/configuration/config.yaml index 82805b0..7b99405 100644 --- a/configuration/config.yaml +++ b/configuration/config.yaml @@ -4,8 +4,10 @@ listen_port: 2240 web_port: 8088 -# These settings make sure that connections are not blocked because they use an old version of TLS. This was probably the most annoying problem to solve for me. -# Note that not all of these settings are actually used; some are just for compatability with older versions and are ignored. +# These settings make sure that connections are not blocked because they use an +# old version of TLS. This was probably the most annoying problem to solve for +# me. Note that not all of these settings are actually used; some are just for +# compatability with older versions and are ignored. ssl_insecure: true upstream_cert: false tls_version_server_min: UNBOUNDED @@ -15,7 +17,7 @@ ssl_version_client: all ciphers_client: all ciphers_server: all -# These just make sure that the right configuration files and certificates are loaded. +# These just make sure that the right configuration files and certs are loaded. client_certs: ./client-certificates confdir: ./configuration @@ -25,7 +27,7 @@ scripts: ./pretendo_addon.py # This simply attempts makes sure that no requests are cached. anticache: true -# Just convenience features +# A couple convenience features console_focus_follow: true showhost: true -console_palette: dark \ No newline at end of file +console_palette: dark From e89e6e8a62884d2580b366e7882b0bdd2597bfee Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Mon, 30 Aug 2021 19:27:01 -0400 Subject: [PATCH 05/74] Update the launch script to prevent quoting issues --- launch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launch b/launch index 262f76c..4c1bb0c 100755 --- a/launch +++ b/launch @@ -1,4 +1,4 @@ #!/bin/bash -cd $(realpath --no-symlinks $(dirname $0)) -$(basename $0) --set confdir="./configuration" $* +cd "$(realpath --no-symlinks "$(dirname "$0")")" +$(basename "$0") --set confdir="./configuration" "$@" From 9b6da245125bb88f3190cae30a1b3171f496b969 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Mon, 30 Aug 2021 19:29:24 -0400 Subject: [PATCH 06/74] Format the Pretendo addon script --- pretendo_addon.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/pretendo_addon.py b/pretendo_addon.py index 8eef8ec..dfdb7a4 100644 --- a/pretendo_addon.py +++ b/pretendo_addon.py @@ -4,17 +4,17 @@ class PretendoAddon: def load(self, loader) -> None: loader.add_option( - name='pretendo_redirect', - typespec = bool, - default = False, - help='Redirect all requests from Nintendo to Pretendo' + name="pretendo_redirect", + typespec=bool, + default=False, + help="Redirect all requests from Nintendo to Pretendo", ) loader.add_option( - name='pretendo_http', - typespec = bool, - default = False, - help='Sets Pretendo requests to HTTP' + name="pretendo_http", + typespec=bool, + default=False, + help="Sets Pretendo requests to HTTP", ) def request(self, flow: http.HTTPFlow) -> None: @@ -23,8 +23,4 @@ def request(self, flow: http.HTTPFlow) -> None: flow.request.host = flow.request.host.replace('nintendo.net', 'pretendo.cc') if ctx.options.pretendo_http: - flow.request.scheme = 'http' - -addons = [ - PretendoAddon() -] \ No newline at end of file +addons = [PretendoAddon()] From 827f6a0af6cb40f3f76126129e68ae655040ff37 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Mon, 30 Aug 2021 19:40:53 -0400 Subject: [PATCH 07/74] Allow redirecting traffic from multiple servers in the addon This replaces the simple "nintendo.net => pretendo.cc" substitution with a customized redirection for each Pretendo server. This is necessary for several reasons: - The Grove server expects `eshop.pretendo.cc`, not `geisha-wup`... - Each server must be run on a different port. The port numbers must be configured manually for each Pretendo server. --- pretendo_addon.py | 61 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/pretendo_addon.py b/pretendo_addon.py index dfdb7a4..8139a0c 100644 --- a/pretendo_addon.py +++ b/pretendo_addon.py @@ -2,25 +2,62 @@ class PretendoAddon: - def load(self, loader) -> None: - loader.add_option( + def load(self, loader) -> None: + loader.add_option( name="pretendo_redirect", typespec=bool, default=False, help="Redirect all requests from Nintendo to Pretendo", - ) + ) - loader.add_option( + loader.add_option( name="pretendo_http", typespec=bool, default=False, help="Sets Pretendo requests to HTTP", - ) - - def request(self, flow: http.HTTPFlow) -> None: - if ctx.options.pretendo_redirect: - if 'nintendo.net' in flow.request.host: - flow.request.host = flow.request.host.replace('nintendo.net', 'pretendo.cc') - - if ctx.options.pretendo_http: + ) + + def request(self, flow: http.HTTPFlow) -> None: + if not ctx.options.pretendo_redirect: + # This script should just be disabled + return + + # The account server + if "account.nintendo.net" in flow.request.host: + flow.request.host = flow.request.host.replace("nintendo.net", "pretendo.cc") + flow.request.port = 7070 + + if ctx.options.pretendo_http: + flow.request.scheme = "http" + + # The Grove eShop server + if "geisha-wup.cdn.nintendo.net" in flow.request.host: + flow.request.host = flow.request.host.replace( + "geisha-wup.cdn.nintendo.net", "eshop.pretendo.cc" + ) + flow.request.port = 8081 + + if ctx.options.pretendo_http: + flow.request.scheme = "http" + + # The olv-api Miiverse API server + if ( + "discovery.olv.nintendo.net" in flow.request.host + or "api.olv.nintendo.net" in flow.request.host + ): + flow.request.host = flow.request.host.replace("nintendo.net", "pretendo.cc") + flow.request.port = 8082 + + if ctx.options.pretendo_http: + flow.request.scheme = "http" + + # The Juxtaposition Miiverse server + elif "olv.nintendo.net" in flow.request.host: + flow.request.host = flow.request.host.replace("nintendo.net", "pretendo.cc") + flow.request.port = 8083 + + if ctx.options.pretendo_http: + flow.request.scheme = "http" + + addons = [PretendoAddon()] From 62d47316b8894151204b9eed3d870379d024f1e4 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Mon, 30 Aug 2021 20:01:00 -0400 Subject: [PATCH 08/74] Update some usage information in the readme --- readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 13bc756..85c25d0 100644 --- a/readme.md +++ b/readme.md @@ -7,6 +7,7 @@ A package for intercepting traffic from the WiiU and 3DS - mitmproxy (https://mitmproxy.org/) - a *nix system (macos, linux, untested on WSL) - SSL patches for your console ([3DS SSL Patch](https://github.com/InternalLoss/3DS-SSL-Patch), [WiiU SSL Patch](https://github.com/PretendoNetwork/network-installer/tree/nossl-5.5.5)) + - Alternatively, you can replace the `CACERT_NINTENDO_CA_G3.der` file with the mitmproxy CA cert. ## Usage @@ -14,7 +15,7 @@ A package for intercepting traffic from the WiiU and 3DS - Run one of the launcher scripts to launch a proxy server - Configure your console to connect to the proxy -For use with Pretendo run with the option `--scripts ./pretendo_addon.py`. This will add the custom `pretendo_redirect` and `pretendo_http` options +Running the launcher script will now automatically load the Pretendo addon script. This will add the custom `pretendo_redirect` and `pretendo_http` options to mitmproxy. ## Known issues From c2d40776ddffc774f8d1afae48b5a410af5ba424 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Mon, 30 Aug 2021 20:04:37 -0400 Subject: [PATCH 09/74] Fix angle brackets in the readme --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 85c25d0..147dcee 100644 --- a/readme.md +++ b/readme.md @@ -20,5 +20,5 @@ Running the launcher script will now automatically load the Pretendo addon scrip ## Known issues - WiiU eShop does not work (crashes on boot) -- Occasionally, a site will not work and cause a certificate warning in the mitmproxy logs. If this happens, go into the client-certificate directory of this repository and create a symbolic link to ctr-common-1.pem if you are using a 3DS or WIIU_COMMON_CERT_1.pem if you are using a Wii U named .pem and try again. +- Occasionally, a site will not work and cause a certificate warning in the mitmproxy logs. If this happens, go into the client-certificate directory of this repository and create a symbolic link to ctr-common-1.pem if you are using a 3DS or WIIU_COMMON_CERT_1.pem if you are using a Wii U named \.pem and try again. - It is not possible to use SSLv3 or SSLv2 using the latest version of mitmproxy with OpenSSL. This might cause problems with certain servers. There is currently no workaround for this because OpenSSL 1.1.x has completely removed support for old versions of SSL. From c0821b546eac55079ef9893ea2806bb975f062a1 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 1 Sep 2021 16:38:00 -0400 Subject: [PATCH 10/74] Change the account server to listen on port 8080 This makes more sense than listening on port 7070 because the account server is the most important. --- pretendo_addon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pretendo_addon.py b/pretendo_addon.py index 8139a0c..b80a036 100644 --- a/pretendo_addon.py +++ b/pretendo_addon.py @@ -25,7 +25,7 @@ def request(self, flow: http.HTTPFlow) -> None: # The account server if "account.nintendo.net" in flow.request.host: flow.request.host = flow.request.host.replace("nintendo.net", "pretendo.cc") - flow.request.port = 7070 + flow.request.port = 8080 if ctx.options.pretendo_http: flow.request.scheme = "http" From 1d7b2609e80bdd23e789ce05c37bd0a5073da69d Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 1 Sep 2021 20:16:54 -0400 Subject: [PATCH 11/74] Creat a simple Pretendo Network setup script This creates a script for setting up the Pretendo network servers. Currently, it only downloads several relevant Git repositories and Go libraries and organizes them. I plan to continue working on this script so it will be able to fully set up and configure all of the servers. --- setup-pretendo.sh | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 setup-pretendo.sh diff --git a/setup-pretendo.sh b/setup-pretendo.sh new file mode 100644 index 0000000..d63d13e --- /dev/null +++ b/setup-pretendo.sh @@ -0,0 +1,57 @@ +# Set up some ANSI codes +reset="\e[0m" +title="\e[1;34m" +subtitle="\e[36m" +warning="\e[33mWarning: " +error="\e[1;31mError: " + +# Header message +echo -e $title"Simple Pretendo Network setup script"$reset +printf '\e]2;Pretendo setup\a' +echo + +# Check that required depedencies are installed +echo -e $subtitle"Git version:"$reset +git --version || echo -e $error"Git is not installed." +echo -e $subtitle"Node.js version:"$reset +node --version || echo -e $error"Node.js is not installed." +echo -e $subtitle"npm version:"$reset +npm --version || echo -e $error"NPM is not installed." +echo -e $subtitle"Go version:"$reset +go version || echo -e $error"Go is not installed." +echo -e $subtitle"MongoDB version:"$reset +mongod --version || echo -e $error"MongoDB is not installed." + +# Make sure that a Pretendo folder does not already exist +if [ -d ./PretendoNetwork ]; then + echo -e $warning"The \"PretendoNetwork\" folder already exists! It will be deleted if you continue!"$reset +fi + +# Everything should be set up fine now. It is time to actually start the setup. +echo -e $title"Ready to start downloading the Pretendo files!"$reset +read -p "Would you like to continue? [y/N] " -r +if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1; fi + +# Create the PretendoNetwork folder +rm -rf PretendoNetwork +mkdir PretendoNetwork +cd PretendoNetwork + +# Start by downloading the relevant GitHub repositories +echo -e $title"Cloning the server repositories from GitHub"$reset +git clone --depth 1 https://github.com/PretendoNetwork/account +git clone --depth 1 https://github.com/PretendoNetwork/BOSS +git clone --depth 1 https://github.com/PretendoNetwork/friends-authentication +git clone --depth 1 https://github.com/PretendoNetwork/friends-secure +git clone --depth 1 https://github.com/PretendoNetwork/Grove +git clone --depth 1 https://github.com/PretendoNetwork/juxt-web +git clone --depth 1 https://github.com/PretendoNetwork/olv-api +git clone --depth 1 https://github.com/PretendoNetwork/SOAP +git clone --depth 1 https://github.com/PretendoNetwork/super-mario-maker-authentication +git clone --depth 1 https://github.com/PretendoNetwork/super-mario-maker-secure + +# Then download the Go libraries +echo -e $title"Downloading the Go libraries"$reset +go get github.com/PretendoNetwork/nex-go +go get github.com/PretendoNetwork/nex-protocols-go +go get go.mongodb.org/mongo-driver From 3870d966289f23cc2e43b2ca92c4c7429e1ef88f Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 2 Sep 2021 11:28:13 -0400 Subject: [PATCH 12/74] Make the setup script executable --- setup-pretendo.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 setup-pretendo.sh diff --git a/setup-pretendo.sh b/setup-pretendo.sh old mode 100644 new mode 100755 From a4aef308ddb7a4099efcbf7556b95e867b02576e Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 2 Sep 2021 11:58:17 -0400 Subject: [PATCH 13/74] Update the client certificates Downloaded from https://github.com/larsenv/NintendoCerts --- client-certificates/WIIU_ACCOUNT_1_CERT.pem | 56 +++++++++++++++++++++ client-certificates/WIIU_COMMON_1_CERT.pem | 7 --- client-certificates/ctr-common-1.pem | 55 ++++++++++---------- 3 files changed, 84 insertions(+), 34 deletions(-) create mode 100644 client-certificates/WIIU_ACCOUNT_1_CERT.pem diff --git a/client-certificates/WIIU_ACCOUNT_1_CERT.pem b/client-certificates/WIIU_ACCOUNT_1_CERT.pem new file mode 100644 index 0000000..62a61eb --- /dev/null +++ b/client-certificates/WIIU_ACCOUNT_1_CERT.pem @@ -0,0 +1,56 @@ +-----BEGIN CERTIFICATE----- +MIIExjCCA66gAwIBAgIBKjANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQGEwJVUzET +MBEGA1UECBMKV2FzaGluZ3RvbjEhMB8GA1UEChMYTmludGVuZG8gb2YgQW1lcmlj +YSBJbmMuMQswCQYDVQQLEwJJUzEZMBcGA1UEAxMQTmludGVuZG8gQ0EgLSBHMzAe +Fw0xMjA2MDcxNzI3NThaFw0zODAxMTIxNzI3NThaMIGoMQswCQYDVQQGEwJVUzET +MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEiMCAGA1UEChMZ +TmludGVuZG8gb2YgQW1lcmljYSwgSW5jLjELMAkGA1UECxMCSVQxHTAbBgNVBAMT +FFdpaSBVIEFjY291bnQgUHJvZCAxMSIwIAYJKoZIhvcNAQkBFhNjYUBub2Eubmlu +dGVuZG8uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtDA04vmM +KuTzFm8BVPvzaEjAvPN5B7baCjgYimTznFNyrqep1L3Imc85KOUIRPLW4UT0x2ob +mQmKJRcBl9s7/tr0lNgUUOTzFd3UfKJUSk2plYtAyCiYfddCL7cfIdGXBOMlCjcY +Bk7/rOixyzW8psF+wmL4HkGKBu81aVaCt19yA1alydi1laA6wZOBiNvPwwPOPZnQ +cKkIRCO+NC2VxXxJCccbQ3/LT+n+TIgegKe++yUL+eR7aJby6r1u4FHeszHuFSu2 +X32p+Wh4YFzuiwuGJWjWrMMbnYjmlaaGLVQurzOj8nGV9U1xKe6CuSVN7ddZVlcm +Ez8onCkGM0cbOwIDAQABo4IBMzCCAS8wCQYDVR0TBAIwADAsBglghkgBhvhCAQ0E +HxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFJSb91rD +nsvZF9DYVpUJuoi0S5kTMIGXBgNVHSMEgY8wgYyAFATT3tP98MjrwlmSh/sf1z5y ++O35oXGkbzBtMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEhMB8G +A1UEChMYTmludGVuZG8gb2YgQW1lcmljYSBJbmMuMQswCQYDVQQLEwJJUzEZMBcG +A1UEAxMQTmludGVuZG8gQ0EgLSBHM4IBATA7BgNVHR8ENDAyMDCgLqAshipodHRw +Oi8vY3JsLm5pbnRlbmRvLmNvbS9uaW50ZW5kby1jYS1nMy5jcmwwDQYJKoZIhvcN +AQELBQADggEBAI7dp6gt5w5+SolgO4C2W7Ywv2uvz/6SdVr4mDPDWTH/uHCCMw+D +yd29DT289LeQpUQAB3ojH+kCq3wrBXENBGQqTIdAoWhFiXgaUDPGkOIDmKSmRHF3 +3LKudQ7UvTQyx1W1oigZoho6p8OcsdJ+oBAjH2s1TBn5NDXlBJHWmQRAmYjnJDHR +lmYCKmOW3ZU9XtV9CNojvxd2mt+hsT8M+Zt+JjLrPkwpWe2jZxk+V+0hjk5+yPBA +ur9ttws8qqVfxlIfm1xosP0Pu3gxDaJz45VvKskpJFMyUN1D7mlxAnyR+DFO/NYj +qaKn0AZyGHTutBKG0s2tTpE0xpNLKmCdyns= +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC0MDTi+Ywq5PMW +bwFU+/NoSMC883kHttoKOBiKZPOcU3Kup6nUvciZzzko5QhE8tbhRPTHahuZCYol +FwGX2zv+2vSU2BRQ5PMV3dR8olRKTamVi0DIKJh910Ivtx8h0ZcE4yUKNxgGTv+s +6LHLNbymwX7CYvgeQYoG7zVpVoK3X3IDVqXJ2LWVoDrBk4GI28/DA849mdBwqQhE +I740LZXFfEkJxxtDf8tP6f5MiB6Ap777JQv55HtolvLqvW7gUd6zMe4VK7Zffan5 +aHhgXO6LC4YlaNaswxudiOaVpoYtVC6vM6PycZX1TXEp7oK5JU3t11lWVyYTPyic +KQYzRxs7AgMBAAECggEASB37LNTgCtLzkAkBqXflpdloerefuzyt6+UjvVBGSE0F +221zhZgnz5emsv1n3+CprCOjLKUFQq0Uw19/3b17N7d+qIwLJY1c1WWhg/icb9jB +hP7lALduwP8EmIBcT3bJUMVwr7P5Q50eq5++eSyawssy5q4hzEpC6h+Xav+a9bTr +wgwN3FxU1T1BEotqznG+pGeek8FmQ9G3xI50+de3SGHPUZp0wJygimZTX0Ujbpqr +YnEipm6PCna4kSAS9zqK1pPHpQc04j1MxAwU/8UKS+RYFODOKvBu97aIYmMbVGZi +0s87E7NO9umioa8aj4HvPQmc2KwqppOfUVGP/NkhsQKBgQDbIPkIbriOhMP+/qVl +LH2D+ciMxTnMKbhYAzYgVnYSRz9UEODTdFUidD46XXclx0OJ0kjGz27FD5A9XhAF +OCSOdsG2sXG06ZMl9enRfBMnAikFXMKinxvB0DljsyzkujFBNcJJ0S+8V2+hIEaz +e3gGg8O8iOmmdzCl5lteGcTYBwKBgQDSgdzJNmhEGILZmWM3JKJosXQ5Vi1I9G5N +Jlca9ujyJiKlunBb4nBGXxuTeHXDnSBCigsqSqLJzIG2O/UbgdNixNDlGz3rlaI5 +g3oI+rdDsKPYZT8hJCxqw1xGslg8PsmdBbXY+prGaD17mjhymEM9tCA0LKd1eL41 +NUIKGo1OLQKBgGwbt2FWps0BaWULovPoYEBVYoE46Iv2ZVFevDx2C6h26CKEdTc9 +pKbr7KuE4zyLM6HyUh9rxX2JcSMlngfFLBvxMR7+KlgUCJno2iOU8CoFodFYc1oh +32LeZQHwKwzpY1WFvUYH42IrTRKURu1T0+J67X29mnCbSy/+F0O0uO3PAoGAP4PL +WDLAVvuGT52GYBb/odMZHEuyMjb+KO0OjyY8twNmpNaSHEdAVRtROLe54KHCIBGC +uOn4ICdCY/fHRttvKnf0B4ymrDRj1DKlWZw8O4JKjXpPB/LgK/5yEyqwkMzpDCWy +7pr+pCrDkk3ABmOGtlFo/hUTGdCqo2dEW8QTKqkCgYAL6PYro/q5oE8mFaqNBlUO +8FK9Q1qvMSZxyGXAqfzJdBY77jbMtuo3ceSkJoKRtXvi5UcyCsebYqxJ7hmDx2Bi +v66OZmYb+4RqA4w0+DzAfU6l+vVWe00nZP58kZgz+34vTCKRwk0BtxPmJw0pzgCy +jMWTuCHskBrSGt49kzrbxQ== +-----END PRIVATE KEY----- diff --git a/client-certificates/WIIU_COMMON_1_CERT.pem b/client-certificates/WIIU_COMMON_1_CERT.pem index c8efaec..d1152ad 100644 --- a/client-certificates/WIIU_COMMON_1_CERT.pem +++ b/client-certificates/WIIU_COMMON_1_CERT.pem @@ -1,7 +1,3 @@ -Bag Attributes - localKeyID: B5 CB 90 50 3A 55 5C 55 D5 93 74 82 9B 42 02 BD 44 D8 83 9B -subject=/C=US/ST=Washington/L=Redmond/O=Nintendo of America Inc./OU=IT/CN=Wii U Common Prod 1/emailAddress=ca@noa.nintendo.com -issuer=/C=US/ST=Washington/O=Nintendo of America Inc./OU=IS/CN=Nintendo CA - G3 -----BEGIN CERTIFICATE----- MIIExDCCA6ygAwIBAgIBGDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQGEwJVUzET MBEGA1UECBMKV2FzaGluZ3RvbjEhMB8GA1UEChMYTmludGVuZG8gb2YgQW1lcmlj @@ -30,9 +26,6 @@ VXzk/33BLe386iJuLzOOqOuM025F3+CUU0isz3812Lf6GegfiNaBpfPfa2sv7EDD WVRiGgt+bw3MJefwax05xcgLHsJZtf/N+e+84IHsM0oyEOfqlGWpFb5Tle9np8yU kv12EjQy/Y6OJ8qkE95Ry9U1gK9t/RMm -----END CERTIFICATE----- -Bag Attributes - localKeyID: B5 CB 90 50 3A 55 5C 55 D5 93 74 82 9B 42 02 BD 44 D8 83 9B -Key Attributes: -----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCoR5vkVD5lKgb2 HNRpPn25dio7Dem77REw0r7V2pObHinxWHUkPkZHfEhfOvtrsE/ZvJW28Si6SG7H diff --git a/client-certificates/ctr-common-1.pem b/client-certificates/ctr-common-1.pem index 43bcf7c..dbcf9b4 100644 --- a/client-certificates/ctr-common-1.pem +++ b/client-certificates/ctr-common-1.pem @@ -26,30 +26,31 @@ ahbvwpe1t3GSNOS5nBDSeCHAKLmzfnXpliA5qQZxo94RSXIVWK8hilXoFDQCL904 OGpgZnAhz4p3rcJYTq9ub8n6NYr9OJKKbWXfJY1QK4pXFVcIuAph0o/EyzDIEXuT J4Q4b2km8uI0H4yxsQwUX9Epw6Vbujc= -----END CERTIFICATE----- ------BEGIN RSA PRIVATE KEY----- -MIIEpgIBAAKCAQEA81Vzs324jZwcNpbFESgDNooVTRP1TlxvYwz8bbHnJHhImjEJ -NO29YSTpjmF7wonczooeKXfE/Ry2+ey9mk92UhzSnvuSHQ6P2zFBbcPnE8eBi73o -DnErgixiWe1TKP1G5LvwOqrEkVmXLN/qnLrsfFp4QNyFc+PLvJ9IAfRSBwdRJHAi -SgE9nB9eI7AGcM6DCw7+p9zEz6rNRHUVRc5I132wJpQa8aoWaqPW7LE8exEC3VSf -DHRVPjZUMRhfoBVSi2NfiA3xYsqkv+Ct3E+bzW8y1aAQ7wIshQ/RGcLtVZE+tkoA -znXewVLdKtcC67Vy4awhJ/BqK1tvc26qV3zIJwIDAQABAoIBAQDBTk4m9iYJoU2s -dCPDmFTNG+8GF2fVw4rdVjCmeCDWkROkInZc7Mx4gtljub+WcOzPy1tgt/vu08Ps -UYziLGQjoTAVCmct3CaeC8gdifZleSVJvSi/aFoXBGlxZR6ePm72QPL7uDOGAHUf -OhboQXqi40AKzuTZhsqQYrzSiKQtXa8M0jMj3XWb7q+wLEyCtGJvUsFjfXiuxdrg -ZMwJ3jroDkxAIatmZzzAcjbY6U78P574DQAeFJM/6KJrZXgmsPdkqEpUJWBs1Zro -b7eEKjkM0tVfk6GrlIZgD5lhBxdyCci9UomO1JjJakKBhVeiB+HMC4sJtcJPyBdb -ZH70dIJhAoGBAP74UyWJ/xnd12NrZrybOab5pCSYDcaoLpzghWcaxsX+AS70BpEZ -wZU+DMxWtSfGTbVOlTlW0LEu3A9JHtisr+a3bf+ytv2zXRuDnJ3fhnFqRLRfopNs -BEAePBUL2EkJ/8OTSsiZcmDoVyhnt14U4sleawsIi30T/KcQDtMS81YXAoGBAPRR -F/oZcWHYNm1X8foHiPbltAji4u5M3McZT4wb3RZbWLJbUjSz/tATah36dxuT1v1z -EwHWZ0vdN94MuIy1OnwIHvBXJy8m4Rq6VTQpzGPgy0clbZbtX3Cih+fQSvxJUe2m -psaicsNSTtmd+btudZyG5qzILOU8afGmeB1wr3hxAoGBANZkcm3XSoUyj8FOdxXS -pDiuI4KNxM+tbXyGIkZfMpMbkV0s3jS2ZpuakGJl6m/mhEMXL80GHfdOwsWro19o -XYRv6vOeD9bmMj1HfrMVWFQXmmvdGrRBmJVdlwHPcu9/k+uc974ToSSxWVBlXb+j -aksOtI2Tgs8KtmC31O9ROQHDAoGBAI0OnPdK5UmGmbX7xruCyjMyYAWZaUgInJdf -J6xPEhCsYMNpMkc3fPEJpIT2bPpBGylt3RV8glsst+q+EXc70y51SdedmgQBQIo7 -9qGNWHJ6ASNsmp8/IZFYZXsTqZeLhX/ebf/VHsliph/Cs8LhfYoH4Pr0/+bCQLDC -Wis1OjohAoGBAJSivkSk2MKrg/t4CqNYLBiPp0fegm9ZL3187I/leVJGXIXsNqTq -oa6qT5JxiJRQnkw2IzfI6icl+BJYydRU3oH4X0nvl0eyjiIfG/nfn4H7ckSKdzP/ -wVBdRbcC+/PX/1WpGiJM+kXrf/vLQN1B6iihrYEkS/ZIkzFWMuuKQRvQ ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDzVXOzfbiNnBw2 +lsURKAM2ihVNE/VOXG9jDPxtseckeEiaMQk07b1hJOmOYXvCidzOih4pd8T9HLb5 +7L2aT3ZSHNKe+5IdDo/bMUFtw+cTx4GLvegOcSuCLGJZ7VMo/Ubku/A6qsSRWZcs +3+qcuux8WnhA3IVz48u8n0gB9FIHB1EkcCJKAT2cH14jsAZwzoMLDv6n3MTPqs1E +dRVFzkjXfbAmlBrxqhZqo9bssTx7EQLdVJ8MdFU+NlQxGF+gFVKLY1+IDfFiyqS/ +4K3cT5vNbzLVoBDvAiyFD9EZwu1VkT62SgDOdd7BUt0q1wLrtXLhrCEn8GorW29z +bqpXfMgnAgMBAAECggEBAMFOTib2JgmhTax0I8OYVM0b7wYXZ9XDit1WMKZ4INaR +E6QidlzszHiC2WO5v5Zw7M/LW2C3++7Tw+xRjOIsZCOhMBUKZy3cJp4LyB2J9mV5 +JUm9KL9oWhcEaXFlHp4+bvZA8vu4M4YAdR86FuhBeqLjQArO5NmGypBivNKIpC1d +rwzSMyPddZvur7AsTIK0Ym9SwWN9eK7F2uBkzAneOugOTEAhq2ZnPMByNtjpTvw/ +nvgNAB4Ukz/oomtleCaw92SoSlQlYGzVmuhvt4QqOQzS1V+ToauUhmAPmWEHF3IJ +yL1SiY7UmMlqQoGFV6IH4cwLiwm1wk/IF1tkfvR0gmECgYEA/vhTJYn/Gd3XY2tm +vJs5pvmkJJgNxqgunOCFZxrGxf4BLvQGkRnBlT4MzFa1J8ZNtU6VOVbQsS7cD0ke +2Kyv5rdt/7K2/bNdG4Ocnd+GcWpEtF+ik2wEQB48FQvYSQn/w5NKyJlyYOhXKGe3 +XhTiyV5rCwiLfRP8pxAO0xLzVhcCgYEA9FEX+hlxYdg2bVfx+geI9uW0COLi7kzc +xxlPjBvdFltYsltSNLP+0BNqHfp3G5PW/XMTAdZnS9033gy4jLU6fAge8FcnLybh +GrpVNCnMY+DLRyVtlu1fcKKH59BK/ElR7aamxqJyw1JO2Z35u251nIbmrMgs5Txp +8aZ4HXCveHECgYEA1mRybddKhTKPwU53FdKkOK4jgo3Ez61tfIYiRl8ykxuRXSze +NLZmm5qQYmXqb+aEQxcvzQYd907CxaujX2hdhG/q854P1uYyPUd+sxVYVBeaa90a +tEGYlV2XAc9y73+T65z3vhOhJLFZUGVdv6NqSw60jZOCzwq2YLfU71E5AcMCgYEA +jQ6c90rlSYaZtfvGu4LKMzJgBZlpSAicl18nrE8SEKxgw2kyRzd88QmkhPZs+kEb +KW3dFXyCWyy36r4RdzvTLnVJ152aBAFAijv2oY1YcnoBI2yanz8hkVhlexOpl4uF +f95t/9UeyWKmH8KzwuF9igfg+vT/5sJAsMJaKzU6OiECgYEAlKK+RKTYwquD+3gK +o1gsGI+nR96Cb1kvfXzsj+V5UkZchew2pOqhrqpPknGIlFCeTDYjN8jqJyX4EljJ +1FTegfhfSe+XR7KOIh8b+d+fgftyRIp3M//BUF1FtwL789f/VakaIkz6Ret/+8tA +3UHqKKGtgSRL9kiTMVYy64pBG9A= +-----END PRIVATE KEY----- From 0e745461dffd9e212f17c94e87325f39ea785d94 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 24 Nov 2021 15:18:04 -0500 Subject: [PATCH 14/74] Use a loop for cloning the repositories --- setup-pretendo.sh | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/setup-pretendo.sh b/setup-pretendo.sh index d63d13e..3f1f919 100755 --- a/setup-pretendo.sh +++ b/setup-pretendo.sh @@ -39,16 +39,11 @@ cd PretendoNetwork # Start by downloading the relevant GitHub repositories echo -e $title"Cloning the server repositories from GitHub"$reset -git clone --depth 1 https://github.com/PretendoNetwork/account -git clone --depth 1 https://github.com/PretendoNetwork/BOSS -git clone --depth 1 https://github.com/PretendoNetwork/friends-authentication -git clone --depth 1 https://github.com/PretendoNetwork/friends-secure -git clone --depth 1 https://github.com/PretendoNetwork/Grove -git clone --depth 1 https://github.com/PretendoNetwork/juxt-web -git clone --depth 1 https://github.com/PretendoNetwork/olv-api -git clone --depth 1 https://github.com/PretendoNetwork/SOAP -git clone --depth 1 https://github.com/PretendoNetwork/super-mario-maker-authentication -git clone --depth 1 https://github.com/PretendoNetwork/super-mario-maker-secure +repositories=("account" "BOSS" "friends-authentication" "friends-secure" "Grove" "juxt-web" "olv-api" "SOAP" "super-mario-maker-authentication" "super-mario-maker-secure") +for repo in ${repositories[@]}; do + echo -e $subtitle"Cloning repository PretendoNetwork/$repo"$reset + echo git clone --depth 1 https://github.com/PretendoNetwork/$repo +done # Then download the Go libraries echo -e $title"Downloading the Go libraries"$reset From 9254076deb68cebf97b205111ec3e8025173ad06 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 24 Nov 2021 15:20:44 -0500 Subject: [PATCH 15/74] Add the Wii U Chat repositories --- setup-pretendo.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup-pretendo.sh b/setup-pretendo.sh index 3f1f919..c3d7a59 100755 --- a/setup-pretendo.sh +++ b/setup-pretendo.sh @@ -39,7 +39,7 @@ cd PretendoNetwork # Start by downloading the relevant GitHub repositories echo -e $title"Cloning the server repositories from GitHub"$reset -repositories=("account" "BOSS" "friends-authentication" "friends-secure" "Grove" "juxt-web" "olv-api" "SOAP" "super-mario-maker-authentication" "super-mario-maker-secure") +repositories=("account" "BOSS" "friends-authentication" "friends-secure" "Grove" "juxt-web" "olv-api" "SOAP" "super-mario-maker-authentication" "super-mario-maker-secure" "wiiu-chat-authentication" "wiiu-chat-secure") for repo in ${repositories[@]}; do echo -e $subtitle"Cloning repository PretendoNetwork/$repo"$reset echo git clone --depth 1 https://github.com/PretendoNetwork/$repo From 36cf6832079156c5360caef8e247c794744c98c0 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 24 Nov 2021 15:23:38 -0500 Subject: [PATCH 16/74] Add the MarioKart 7 and 8 repositories --- setup-pretendo.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup-pretendo.sh b/setup-pretendo.sh index c3d7a59..796d55d 100755 --- a/setup-pretendo.sh +++ b/setup-pretendo.sh @@ -39,7 +39,7 @@ cd PretendoNetwork # Start by downloading the relevant GitHub repositories echo -e $title"Cloning the server repositories from GitHub"$reset -repositories=("account" "BOSS" "friends-authentication" "friends-secure" "Grove" "juxt-web" "olv-api" "SOAP" "super-mario-maker-authentication" "super-mario-maker-secure" "wiiu-chat-authentication" "wiiu-chat-secure") +repositories=("account" "BOSS" "friends-authentication" "friends-secure" "Grove" "juxt-web" "mk7-authentication" "mk7-secure" "mk8-authentication" "mk8-secure" "olv-api" "SOAP" "super-mario-maker-authentication" "super-mario-maker-secure" "wiiu-chat-authentication" "wiiu-chat-secure") for repo in ${repositories[@]}; do echo -e $subtitle"Cloning repository PretendoNetwork/$repo"$reset echo git clone --depth 1 https://github.com/PretendoNetwork/$repo From 1f4c0a1b09e73e917de87a6a134513c90d8bdb20 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Fri, 3 Dec 2021 16:49:16 -0500 Subject: [PATCH 17/74] Fix a string type error --- configuration/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration/config.yaml b/configuration/config.yaml index 7b99405..47db477 100644 --- a/configuration/config.yaml +++ b/configuration/config.yaml @@ -22,7 +22,7 @@ client_certs: ./client-certificates confdir: ./configuration # This enables the Pretendo redirection script. -scripts: ./pretendo_addon.py +scripts: ["./pretendo_addon.py"] # This simply attempts makes sure that no requests are cached. anticache: true From 6f506b8cbcbb7257a8624fb148bcfd5e7c41416d Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sun, 5 Dec 2021 10:31:43 -0500 Subject: [PATCH 18/74] I forgot to remove the test code *facepalm* Also, I improved the formatting a little. --- setup-pretendo.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup-pretendo.sh b/setup-pretendo.sh index 796d55d..0e553cd 100755 --- a/setup-pretendo.sh +++ b/setup-pretendo.sh @@ -28,6 +28,7 @@ if [ -d ./PretendoNetwork ]; then fi # Everything should be set up fine now. It is time to actually start the setup. +echo -e "\n" echo -e $title"Ready to start downloading the Pretendo files!"$reset read -p "Would you like to continue? [y/N] " -r if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1; fi @@ -42,7 +43,7 @@ echo -e $title"Cloning the server repositories from GitHub"$reset repositories=("account" "BOSS" "friends-authentication" "friends-secure" "Grove" "juxt-web" "mk7-authentication" "mk7-secure" "mk8-authentication" "mk8-secure" "olv-api" "SOAP" "super-mario-maker-authentication" "super-mario-maker-secure" "wiiu-chat-authentication" "wiiu-chat-secure") for repo in ${repositories[@]}; do echo -e $subtitle"Cloning repository PretendoNetwork/$repo"$reset - echo git clone --depth 1 https://github.com/PretendoNetwork/$repo + git clone --depth 1 https://github.com/PretendoNetwork/$repo done # Then download the Go libraries From 1d7b14daf83a7f0f5025da3111997d1d4493d394 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sat, 18 Jun 2022 21:23:46 -0400 Subject: [PATCH 19/74] mitmproxy 8.0 updates Recent versions of mitmproxy deprecated these options or made them unnecessary. --- configuration/config.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/configuration/config.yaml b/configuration/config.yaml index 47db477..8bf071e 100644 --- a/configuration/config.yaml +++ b/configuration/config.yaml @@ -12,10 +12,6 @@ ssl_insecure: true upstream_cert: false tls_version_server_min: UNBOUNDED tls_version_client_min: UNBOUNDED -ssl_version_server: all -ssl_version_client: all -ciphers_client: all -ciphers_server: all # These just make sure that the right configuration files and certs are loaded. client_certs: ./client-certificates From 5c12c7f7564faaccaa74190ac9b1bfa5cbddeda2 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 22 Jun 2022 18:37:33 -0400 Subject: [PATCH 20/74] Add client certificates needed for eshop --- client-certificates/ias.wup.shop.nintendo.net.pem | 1 + client-certificates/ninja.wup.shop.nintendo.net.pem | 1 + 2 files changed, 2 insertions(+) create mode 120000 client-certificates/ias.wup.shop.nintendo.net.pem create mode 120000 client-certificates/ninja.wup.shop.nintendo.net.pem diff --git a/client-certificates/ias.wup.shop.nintendo.net.pem b/client-certificates/ias.wup.shop.nintendo.net.pem new file mode 120000 index 0000000..0db523c --- /dev/null +++ b/client-certificates/ias.wup.shop.nintendo.net.pem @@ -0,0 +1 @@ +WIIU_COMMON_1_CERT.pem \ No newline at end of file diff --git a/client-certificates/ninja.wup.shop.nintendo.net.pem b/client-certificates/ninja.wup.shop.nintendo.net.pem new file mode 120000 index 0000000..0db523c --- /dev/null +++ b/client-certificates/ninja.wup.shop.nintendo.net.pem @@ -0,0 +1 @@ +WIIU_COMMON_1_CERT.pem \ No newline at end of file From 5d58cce58d7abefe7fc21c177ae29f007a84c377 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 22 Jun 2022 20:03:46 -0400 Subject: [PATCH 21/74] Simplify client certificates --- client-certificates/{ctr-common-1.pem => CTR-common.pem} | 0 .../{WIIU_ACCOUNT_1_CERT.pem => WiiU-account.pem} | 0 client-certificates/{WIIU_COMMON_1_CERT.pem => WiiU-common.pem} | 0 client-certificates/account.nintendo.net.pem | 1 - client-certificates/account.nintendo.net.pem_wiiu | 1 - client-certificates/ccs.c.shop.nintendowifi.net.pem | 1 - client-certificates/ccs.wup.shop.nintendo.net.pem | 1 - client-certificates/ecs.c.shop.nintendowifi.net.pem | 1 - client-certificates/ecs.wup.shop.nintendo.net.pem | 1 - client-certificates/ias.wup.shop.nintendo.net.pem | 1 - client-certificates/nasc.nintendowifi.net.pem | 1 - client-certificates/ninja.ctr.shop.nintendo.net.pem | 1 - client-certificates/ninja.wup.shop.nintendo.net.pem | 1 - client-certificates/nppl.app.nintendo.net.pem | 1 - client-certificates/nppl.c.app.nintendowifi.net.pem | 1 - client-certificates/npvk.app.nintendo.net.pem | 1 - client-certificates/nus.c.shop.nintendowifi.net.pem | 1 - client-certificates/nus.wup.shop.nintendo.net.pem | 1 - configuration/config.yaml | 2 +- 19 files changed, 1 insertion(+), 16 deletions(-) rename client-certificates/{ctr-common-1.pem => CTR-common.pem} (100%) rename client-certificates/{WIIU_ACCOUNT_1_CERT.pem => WiiU-account.pem} (100%) rename client-certificates/{WIIU_COMMON_1_CERT.pem => WiiU-common.pem} (100%) delete mode 120000 client-certificates/account.nintendo.net.pem delete mode 120000 client-certificates/account.nintendo.net.pem_wiiu delete mode 120000 client-certificates/ccs.c.shop.nintendowifi.net.pem delete mode 120000 client-certificates/ccs.wup.shop.nintendo.net.pem delete mode 120000 client-certificates/ecs.c.shop.nintendowifi.net.pem delete mode 120000 client-certificates/ecs.wup.shop.nintendo.net.pem delete mode 120000 client-certificates/ias.wup.shop.nintendo.net.pem delete mode 120000 client-certificates/nasc.nintendowifi.net.pem delete mode 120000 client-certificates/ninja.ctr.shop.nintendo.net.pem delete mode 120000 client-certificates/ninja.wup.shop.nintendo.net.pem delete mode 120000 client-certificates/nppl.app.nintendo.net.pem delete mode 120000 client-certificates/nppl.c.app.nintendowifi.net.pem delete mode 120000 client-certificates/npvk.app.nintendo.net.pem delete mode 120000 client-certificates/nus.c.shop.nintendowifi.net.pem delete mode 120000 client-certificates/nus.wup.shop.nintendo.net.pem diff --git a/client-certificates/ctr-common-1.pem b/client-certificates/CTR-common.pem similarity index 100% rename from client-certificates/ctr-common-1.pem rename to client-certificates/CTR-common.pem diff --git a/client-certificates/WIIU_ACCOUNT_1_CERT.pem b/client-certificates/WiiU-account.pem similarity index 100% rename from client-certificates/WIIU_ACCOUNT_1_CERT.pem rename to client-certificates/WiiU-account.pem diff --git a/client-certificates/WIIU_COMMON_1_CERT.pem b/client-certificates/WiiU-common.pem similarity index 100% rename from client-certificates/WIIU_COMMON_1_CERT.pem rename to client-certificates/WiiU-common.pem diff --git a/client-certificates/account.nintendo.net.pem b/client-certificates/account.nintendo.net.pem deleted file mode 120000 index 86892e7..0000000 --- a/client-certificates/account.nintendo.net.pem +++ /dev/null @@ -1 +0,0 @@ -ctr-common-1.pem \ No newline at end of file diff --git a/client-certificates/account.nintendo.net.pem_wiiu b/client-certificates/account.nintendo.net.pem_wiiu deleted file mode 120000 index 0db523c..0000000 --- a/client-certificates/account.nintendo.net.pem_wiiu +++ /dev/null @@ -1 +0,0 @@ -WIIU_COMMON_1_CERT.pem \ No newline at end of file diff --git a/client-certificates/ccs.c.shop.nintendowifi.net.pem b/client-certificates/ccs.c.shop.nintendowifi.net.pem deleted file mode 120000 index 86892e7..0000000 --- a/client-certificates/ccs.c.shop.nintendowifi.net.pem +++ /dev/null @@ -1 +0,0 @@ -ctr-common-1.pem \ No newline at end of file diff --git a/client-certificates/ccs.wup.shop.nintendo.net.pem b/client-certificates/ccs.wup.shop.nintendo.net.pem deleted file mode 120000 index 0db523c..0000000 --- a/client-certificates/ccs.wup.shop.nintendo.net.pem +++ /dev/null @@ -1 +0,0 @@ -WIIU_COMMON_1_CERT.pem \ No newline at end of file diff --git a/client-certificates/ecs.c.shop.nintendowifi.net.pem b/client-certificates/ecs.c.shop.nintendowifi.net.pem deleted file mode 120000 index 86892e7..0000000 --- a/client-certificates/ecs.c.shop.nintendowifi.net.pem +++ /dev/null @@ -1 +0,0 @@ -ctr-common-1.pem \ No newline at end of file diff --git a/client-certificates/ecs.wup.shop.nintendo.net.pem b/client-certificates/ecs.wup.shop.nintendo.net.pem deleted file mode 120000 index 0db523c..0000000 --- a/client-certificates/ecs.wup.shop.nintendo.net.pem +++ /dev/null @@ -1 +0,0 @@ -WIIU_COMMON_1_CERT.pem \ No newline at end of file diff --git a/client-certificates/ias.wup.shop.nintendo.net.pem b/client-certificates/ias.wup.shop.nintendo.net.pem deleted file mode 120000 index 0db523c..0000000 --- a/client-certificates/ias.wup.shop.nintendo.net.pem +++ /dev/null @@ -1 +0,0 @@ -WIIU_COMMON_1_CERT.pem \ No newline at end of file diff --git a/client-certificates/nasc.nintendowifi.net.pem b/client-certificates/nasc.nintendowifi.net.pem deleted file mode 120000 index 86892e7..0000000 --- a/client-certificates/nasc.nintendowifi.net.pem +++ /dev/null @@ -1 +0,0 @@ -ctr-common-1.pem \ No newline at end of file diff --git a/client-certificates/ninja.ctr.shop.nintendo.net.pem b/client-certificates/ninja.ctr.shop.nintendo.net.pem deleted file mode 120000 index 86892e7..0000000 --- a/client-certificates/ninja.ctr.shop.nintendo.net.pem +++ /dev/null @@ -1 +0,0 @@ -ctr-common-1.pem \ No newline at end of file diff --git a/client-certificates/ninja.wup.shop.nintendo.net.pem b/client-certificates/ninja.wup.shop.nintendo.net.pem deleted file mode 120000 index 0db523c..0000000 --- a/client-certificates/ninja.wup.shop.nintendo.net.pem +++ /dev/null @@ -1 +0,0 @@ -WIIU_COMMON_1_CERT.pem \ No newline at end of file diff --git a/client-certificates/nppl.app.nintendo.net.pem b/client-certificates/nppl.app.nintendo.net.pem deleted file mode 120000 index 0db523c..0000000 --- a/client-certificates/nppl.app.nintendo.net.pem +++ /dev/null @@ -1 +0,0 @@ -WIIU_COMMON_1_CERT.pem \ No newline at end of file diff --git a/client-certificates/nppl.c.app.nintendowifi.net.pem b/client-certificates/nppl.c.app.nintendowifi.net.pem deleted file mode 120000 index 86892e7..0000000 --- a/client-certificates/nppl.c.app.nintendowifi.net.pem +++ /dev/null @@ -1 +0,0 @@ -ctr-common-1.pem \ No newline at end of file diff --git a/client-certificates/npvk.app.nintendo.net.pem b/client-certificates/npvk.app.nintendo.net.pem deleted file mode 120000 index 0db523c..0000000 --- a/client-certificates/npvk.app.nintendo.net.pem +++ /dev/null @@ -1 +0,0 @@ -WIIU_COMMON_1_CERT.pem \ No newline at end of file diff --git a/client-certificates/nus.c.shop.nintendowifi.net.pem b/client-certificates/nus.c.shop.nintendowifi.net.pem deleted file mode 120000 index 86892e7..0000000 --- a/client-certificates/nus.c.shop.nintendowifi.net.pem +++ /dev/null @@ -1 +0,0 @@ -ctr-common-1.pem \ No newline at end of file diff --git a/client-certificates/nus.wup.shop.nintendo.net.pem b/client-certificates/nus.wup.shop.nintendo.net.pem deleted file mode 120000 index 0db523c..0000000 --- a/client-certificates/nus.wup.shop.nintendo.net.pem +++ /dev/null @@ -1 +0,0 @@ -WIIU_COMMON_1_CERT.pem \ No newline at end of file diff --git a/configuration/config.yaml b/configuration/config.yaml index 8bf071e..47feae3 100644 --- a/configuration/config.yaml +++ b/configuration/config.yaml @@ -14,7 +14,7 @@ tls_version_server_min: UNBOUNDED tls_version_client_min: UNBOUNDED # These just make sure that the right configuration files and certs are loaded. -client_certs: ./client-certificates +client_certs: ./client-certificates/WiiU-common.pem confdir: ./configuration # This enables the Pretendo redirection script. From 3c09da628db234515d0b9d385a712fee2e20ccb4 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 22 Jun 2022 20:10:36 -0400 Subject: [PATCH 22/74] Remove unneeded comments and options from config --- configuration/config.yaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/configuration/config.yaml b/configuration/config.yaml index 47feae3..a367320 100644 --- a/configuration/config.yaml +++ b/configuration/config.yaml @@ -5,11 +5,8 @@ listen_port: 2240 web_port: 8088 # These settings make sure that connections are not blocked because they use an -# old version of TLS. This was probably the most annoying problem to solve for -# me. Note that not all of these settings are actually used; some are just for -# compatability with older versions and are ignored. +# old version of TLS. ssl_insecure: true -upstream_cert: false tls_version_server_min: UNBOUNDED tls_version_client_min: UNBOUNDED From 43c33d777eb7c5b334a1739195a7190e19837cf5 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 22 Jun 2022 20:13:44 -0400 Subject: [PATCH 23/74] Use new Pretendo SSL patch repo --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 147dcee..49a575b 100644 --- a/readme.md +++ b/readme.md @@ -6,7 +6,7 @@ A package for intercepting traffic from the WiiU and 3DS - mitmproxy (https://mitmproxy.org/) - a *nix system (macos, linux, untested on WSL) -- SSL patches for your console ([3DS SSL Patch](https://github.com/InternalLoss/3DS-SSL-Patch), [WiiU SSL Patch](https://github.com/PretendoNetwork/network-installer/tree/nossl-5.5.5)) +- SSL patches for your console ([3DS SSL Patch](https://github.com/InternalLoss/3DS-SSL-Patch), [WiiU SSL Patch](https://github.com/PretendoNetwork/Nimble/releases)) - Alternatively, you can replace the `CACERT_NINTENDO_CA_G3.der` file with the mitmproxy CA cert. ## Usage From 07e500082235c2a15c9570f7fd8d0f5dd234557c Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 22 Jun 2022 20:14:30 -0400 Subject: [PATCH 24/74] Remove outdated known issues section --- readme.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/readme.md b/readme.md index 49a575b..306ae76 100644 --- a/readme.md +++ b/readme.md @@ -16,9 +16,3 @@ A package for intercepting traffic from the WiiU and 3DS - Configure your console to connect to the proxy Running the launcher script will now automatically load the Pretendo addon script. This will add the custom `pretendo_redirect` and `pretendo_http` options to mitmproxy. - -## Known issues - -- WiiU eShop does not work (crashes on boot) -- Occasionally, a site will not work and cause a certificate warning in the mitmproxy logs. If this happens, go into the client-certificate directory of this repository and create a symbolic link to ctr-common-1.pem if you are using a 3DS or WIIU_COMMON_CERT_1.pem if you are using a Wii U named \.pem and try again. -- It is not possible to use SSLv3 or SSLv2 using the latest version of mitmproxy with OpenSSL. This might cause problems with certain servers. There is currently no workaround for this because OpenSSL 1.1.x has completely removed support for old versions of SSL. From 183df7c0b1113c82f22e8e3d3a57b99e0ba049dd Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 22 Jun 2022 20:25:34 -0400 Subject: [PATCH 25/74] Add section on replacing certificates --- readme.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/readme.md b/readme.md index 306ae76..cdff579 100644 --- a/readme.md +++ b/readme.md @@ -16,3 +16,11 @@ A package for intercepting traffic from the WiiU and 3DS - Configure your console to connect to the proxy Running the launcher script will now automatically load the Pretendo addon script. This will add the custom `pretendo_redirect` and `pretendo_http` options to mitmproxy. + +### Replacing server certificates + +1. Back up all of your Wii U's certificates from `/storage_mlc/sys/title/0005001b/10054000/content`. This backup will be necessary to undo any modifications. +2. Convert your mitmproxy certificate to the right format by running the command `openssl x509 -in mitmproxy-ca-cert.pem -outform der -out CACERT_NINTENDO_CA_G3.der` in the `configuration` folder. +3. Upload the created `CACERT_NINTENDO_CA_G3.der` file to `/storage_mlc/sys/title/0005001b/10054000/content/scerts`, replacing the original file. + +To undo this modification, just upload the backup files back to the `content` folder. From bd676b372b0ffbc4b66795318f5c52853cd14930 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 22 Jun 2022 20:32:14 -0400 Subject: [PATCH 26/74] Revert changes to pretendo_addon.py It's better to use an actual reverse proxy like nginx instead of using mitmproxy. --- pretendo_addon.py | 45 +++++---------------------------------------- 1 file changed, 5 insertions(+), 40 deletions(-) diff --git a/pretendo_addon.py b/pretendo_addon.py index b80a036..ecb9f87 100644 --- a/pretendo_addon.py +++ b/pretendo_addon.py @@ -18,46 +18,11 @@ def load(self, loader) -> None: ) def request(self, flow: http.HTTPFlow) -> None: - if not ctx.options.pretendo_redirect: - # This script should just be disabled - return - - # The account server - if "account.nintendo.net" in flow.request.host: - flow.request.host = flow.request.host.replace("nintendo.net", "pretendo.cc") - flow.request.port = 8080 - - if ctx.options.pretendo_http: - flow.request.scheme = "http" - - # The Grove eShop server - if "geisha-wup.cdn.nintendo.net" in flow.request.host: - flow.request.host = flow.request.host.replace( - "geisha-wup.cdn.nintendo.net", "eshop.pretendo.cc" - ) - flow.request.port = 8081 - - if ctx.options.pretendo_http: - flow.request.scheme = "http" - - # The olv-api Miiverse API server - if ( - "discovery.olv.nintendo.net" in flow.request.host - or "api.olv.nintendo.net" in flow.request.host - ): - flow.request.host = flow.request.host.replace("nintendo.net", "pretendo.cc") - flow.request.port = 8082 - - if ctx.options.pretendo_http: - flow.request.scheme = "http" - - # The Juxtaposition Miiverse server - elif "olv.nintendo.net" in flow.request.host: - flow.request.host = flow.request.host.replace("nintendo.net", "pretendo.cc") - flow.request.port = 8083 - + if ctx.options.pretendo_redirect: + if 'nintendo.net' in flow.request.host: + flow.request.host = flow.request.host.replace('nintendo.net', 'pretendo.cc') + if ctx.options.pretendo_http: - flow.request.scheme = "http" - + flow.request.scheme = 'http' addons = [PretendoAddon()] From 6d16a7ae21c629ef3bda576c14bc1491d65bd6fc Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Tue, 28 Jun 2022 19:10:38 -0400 Subject: [PATCH 27/74] Add instructions for compiling OpenSSL This is necessary for distributions that install OpenSSL 3.x.x by default, which is too new for connecting to Nintendo's servers. --- readme.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/readme.md b/readme.md index cdff579..28df897 100644 --- a/readme.md +++ b/readme.md @@ -24,3 +24,20 @@ Running the launcher script will now automatically load the Pretendo addon scrip 3. Upload the created `CACERT_NINTENDO_CA_G3.der` file to `/storage_mlc/sys/title/0005001b/10054000/content/scerts`, replacing the original file. To undo this modification, just upload the backup files back to the `content` folder. + +### Using a custom version of OpenSSL with mitmproxy + +1. Install mitmproxy normally with `pip install mitmproxy`. +2. Get the [latest version](https://www.openssl.org/source/) of **OpenSSL 1.1.1** and download it with `curl https://www.openssl.org/source/openssl-1.1.1(version).tar.gz | tar xz; cd openssl-1.1.1(version)` +3. Compile OpenSSL and Python cryptography according to the [Python cryptography module documentation](https://cryptography.io/en/latest/installation/#build-on-linux): +``` +sudo apt-get install build-essential libffi-dev python3-dev cargo -y +sudo apt-get remove libssl-dev -y +./config -Wl,-Bsymbolic-functions -fPIC shared +sudo make -j8 +sudo make install_sw +openssl version +hash -r +pip install cryptography --no-binary cryptography --force +``` +Running `mitmproxy --version` should now show the custom version of OpenSSL. From 675754d68c6f89c4b324f31d380ff3057f7107fc Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Tue, 28 Jun 2022 19:10:51 -0400 Subject: [PATCH 28/74] Delete setup-pretendo.sh --- setup-pretendo.sh | 53 ----------------------------------------------- 1 file changed, 53 deletions(-) delete mode 100755 setup-pretendo.sh diff --git a/setup-pretendo.sh b/setup-pretendo.sh deleted file mode 100755 index 0e553cd..0000000 --- a/setup-pretendo.sh +++ /dev/null @@ -1,53 +0,0 @@ -# Set up some ANSI codes -reset="\e[0m" -title="\e[1;34m" -subtitle="\e[36m" -warning="\e[33mWarning: " -error="\e[1;31mError: " - -# Header message -echo -e $title"Simple Pretendo Network setup script"$reset -printf '\e]2;Pretendo setup\a' -echo - -# Check that required depedencies are installed -echo -e $subtitle"Git version:"$reset -git --version || echo -e $error"Git is not installed." -echo -e $subtitle"Node.js version:"$reset -node --version || echo -e $error"Node.js is not installed." -echo -e $subtitle"npm version:"$reset -npm --version || echo -e $error"NPM is not installed." -echo -e $subtitle"Go version:"$reset -go version || echo -e $error"Go is not installed." -echo -e $subtitle"MongoDB version:"$reset -mongod --version || echo -e $error"MongoDB is not installed." - -# Make sure that a Pretendo folder does not already exist -if [ -d ./PretendoNetwork ]; then - echo -e $warning"The \"PretendoNetwork\" folder already exists! It will be deleted if you continue!"$reset -fi - -# Everything should be set up fine now. It is time to actually start the setup. -echo -e "\n" -echo -e $title"Ready to start downloading the Pretendo files!"$reset -read -p "Would you like to continue? [y/N] " -r -if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1; fi - -# Create the PretendoNetwork folder -rm -rf PretendoNetwork -mkdir PretendoNetwork -cd PretendoNetwork - -# Start by downloading the relevant GitHub repositories -echo -e $title"Cloning the server repositories from GitHub"$reset -repositories=("account" "BOSS" "friends-authentication" "friends-secure" "Grove" "juxt-web" "mk7-authentication" "mk7-secure" "mk8-authentication" "mk8-secure" "olv-api" "SOAP" "super-mario-maker-authentication" "super-mario-maker-secure" "wiiu-chat-authentication" "wiiu-chat-secure") -for repo in ${repositories[@]}; do - echo -e $subtitle"Cloning repository PretendoNetwork/$repo"$reset - git clone --depth 1 https://github.com/PretendoNetwork/$repo -done - -# Then download the Go libraries -echo -e $title"Downloading the Go libraries"$reset -go get github.com/PretendoNetwork/nex-go -go get github.com/PretendoNetwork/nex-protocols-go -go get go.mongodb.org/mongo-driver From 29aa07cf4eef7058da5a9b34146ead4237ca559a Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 20 Jul 2022 21:09:52 -0400 Subject: [PATCH 29/74] Set up reverse proxy config This reverse proxy listens on port 8888 and forwards all traffic to a local server running on port 81. TCP ports 80 and 443 should be forwarded to port 8888. This local server should be running a reverse proxy like nginx that will proxy requests based on the host header. --- configuration/config.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/configuration/config.yaml b/configuration/config.yaml index a367320..fce53fd 100644 --- a/configuration/config.yaml +++ b/configuration/config.yaml @@ -1,8 +1,11 @@ # See https://docs.mitmproxy.org/stable/concepts-options/ for documentation # An easy-to-remember port that should not conflict with anything -listen_port: 2240 -web_port: 8088 +listen_port: 8888 +web_port: 8089 +mode: reverse:http://127.0.0.1:81 +keep_host_header: true +block_global: false # These settings make sure that connections are not blocked because they use an # old version of TLS. @@ -16,6 +19,7 @@ confdir: ./configuration # This enables the Pretendo redirection script. scripts: ["./pretendo_addon.py"] +pretendo_redirect: true # This simply attempts makes sure that no requests are cached. anticache: true From c4120b7781e336cd5810e6e066b76b2c95078aca Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 20 Jul 2022 21:11:46 -0400 Subject: [PATCH 30/74] Update addon script to work with reverse proxy Use `pretty_host` instead of `host` because `pretty_host` takes the HTTP host header into account, not just the destination. --- pretendo_addon.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pretendo_addon.py b/pretendo_addon.py index ecb9f87..ab20f3f 100644 --- a/pretendo_addon.py +++ b/pretendo_addon.py @@ -19,9 +19,9 @@ def load(self, loader) -> None: def request(self, flow: http.HTTPFlow) -> None: if ctx.options.pretendo_redirect: - if 'nintendo.net' in flow.request.host: - flow.request.host = flow.request.host.replace('nintendo.net', 'pretendo.cc') - + if 'nintendo.net' in flow.request.pretty_host: + flow.request.host = flow.request.pretty_host.replace('nintendo.net', 'pretendo.cc') + if ctx.options.pretendo_http: flow.request.scheme = 'http' From 26764b4d1c7ab3c60df04aa06bec39ee11824f18 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Wed, 20 Jul 2022 22:08:06 -0400 Subject: [PATCH 31/74] Replace request host header instead of host --- pretendo_addon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pretendo_addon.py b/pretendo_addon.py index ab20f3f..c0e5135 100644 --- a/pretendo_addon.py +++ b/pretendo_addon.py @@ -20,7 +20,7 @@ def load(self, loader) -> None: def request(self, flow: http.HTTPFlow) -> None: if ctx.options.pretendo_redirect: if 'nintendo.net' in flow.request.pretty_host: - flow.request.host = flow.request.pretty_host.replace('nintendo.net', 'pretendo.cc') + flow.request.host_header = flow.request.pretty_host.replace('nintendo.net', 'pretendo.cc') if ctx.options.pretendo_http: flow.request.scheme = 'http' From 802eb15c4d914c88651934d47dc5defe7316fb24 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 21 Jul 2022 21:25:31 -0400 Subject: [PATCH 32/74] Also redirect nintendowifi.net for 3DS --- pretendo_addon.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pretendo_addon.py b/pretendo_addon.py index c0e5135..86a7174 100644 --- a/pretendo_addon.py +++ b/pretendo_addon.py @@ -21,6 +21,8 @@ def request(self, flow: http.HTTPFlow) -> None: if ctx.options.pretendo_redirect: if 'nintendo.net' in flow.request.pretty_host: flow.request.host_header = flow.request.pretty_host.replace('nintendo.net', 'pretendo.cc') + elif 'nintendowifi.net' in flow.request.pretty_host: + flow.request.host_header = flow.request.pretty_host.replace('nintendowifi.net', 'pretendo.cc') if ctx.options.pretendo_http: flow.request.scheme = 'http' From a884ccec304b6d4703a6f22e911a9739d09f4a5c Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Fri, 22 Jul 2022 23:34:51 -0400 Subject: [PATCH 33/74] Add support for rverse redirection --- pretendo_addon.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pretendo_addon.py b/pretendo_addon.py index 86a7174..f81631e 100644 --- a/pretendo_addon.py +++ b/pretendo_addon.py @@ -23,6 +23,8 @@ def request(self, flow: http.HTTPFlow) -> None: flow.request.host_header = flow.request.pretty_host.replace('nintendo.net', 'pretendo.cc') elif 'nintendowifi.net' in flow.request.pretty_host: flow.request.host_header = flow.request.pretty_host.replace('nintendowifi.net', 'pretendo.cc') + elif 'rverse.club' in flow.request.pretty_host: + flow.request.host_header = flow.request.pretty_host.replace('rverse.club', 'pretendo.cc') if ctx.options.pretendo_http: flow.request.scheme = 'http' From 13a4b54eb0a999ca41fe96ef67bfd57eba752589 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sun, 28 Aug 2022 23:41:55 -0400 Subject: [PATCH 34/74] Configuration updates for HTTP/2 and caching This removes the anticache option because the server behind the reverse proxy can control caching, and it also disables the somewhat buggy and unnecessary HTTP/2 support. --- configuration/config.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/configuration/config.yaml b/configuration/config.yaml index fce53fd..5b0c821 100644 --- a/configuration/config.yaml +++ b/configuration/config.yaml @@ -7,6 +7,9 @@ mode: reverse:http://127.0.0.1:81 keep_host_header: true block_global: false +# Disable HTTP/2 support, as it seems buggy and is not necessary +http2: false + # These settings make sure that connections are not blocked because they use an # old version of TLS. ssl_insecure: true @@ -21,10 +24,8 @@ confdir: ./configuration scripts: ["./pretendo_addon.py"] pretendo_redirect: true -# This simply attempts makes sure that no requests are cached. -anticache: true - # A couple convenience features console_focus_follow: true showhost: true console_palette: dark +console_layout: vertical From 2269085e70b2c76e696ca5121bf20df0e74c62e3 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Mon, 29 Aug 2022 18:09:56 -0400 Subject: [PATCH 35/74] Also disable insecure SSL settings --- configuration/config.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/configuration/config.yaml b/configuration/config.yaml index 5b0c821..626e474 100644 --- a/configuration/config.yaml +++ b/configuration/config.yaml @@ -10,12 +10,6 @@ block_global: false # Disable HTTP/2 support, as it seems buggy and is not necessary http2: false -# These settings make sure that connections are not blocked because they use an -# old version of TLS. -ssl_insecure: true -tls_version_server_min: UNBOUNDED -tls_version_client_min: UNBOUNDED - # These just make sure that the right configuration files and certs are loaded. client_certs: ./client-certificates/WiiU-common.pem confdir: ./configuration From d427939dd46343fedd170bc3890a797486ba9a93 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 14 Dec 2023 19:26:53 +0000 Subject: [PATCH 36/74] Create WIP mitmproxy-pretendo Dockerfile It doesn't quite work yet. --- Dockerfile | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..98a1e1f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,31 @@ +# The official mitmproxy image uses OpenSSL 3.0.x, which has older versions of +# the SSL and TLS protocols disabled. Unfortunately, the Wii U does not support +# the newer protocols, so we need to compile a custom version of OpenSSL that +# has the older protocols enabled and link it to the Python cryptography +# package. Then, we copy our build of OpenSSL and cryptography to the mitmproxy +# container. This is definitely a hack, but it seems to work. +FROM debian:bookworm AS openssl-build +ARG openssl_version="1.1.1w" openssl_prefix="/opt/openssl" openssl_dir="/usr/lib/ssl" + +# Install build dependencies +RUN apt update +RUN apt install -y curl build-essential python3 python3-dev python3-pip python3-venv libffi-dev cargo pkg-config + +# Download and compile OpenSSL +RUN curl https://www.openssl.org/source/openssl-${openssl_version}.tar.gz | tar -xvz -C /tmp +WORKDIR /tmp/openssl-${openssl_version} +RUN ./config --prefix=${openssl_prefix} --openssldir=${openssl_dir} -Wl,-Bsymbolic-functions -fPIC shared +RUN make -j $(nproc) +RUN make install_sw + +# Create Python cryptography environment +WORKDIR /opt +ENV OPENSSL_DIR=${openssl_prefix} +RUN python3 -m venv cryptography +RUN . ./cryptography/bin/activate && python3 -m pip install cryptography --no-binary cryptography + +# This is the main mitmproxy image that will be run +FROM mitmproxy/mitmproxy:latest AS mitmproxy +ARG openssl_prefix="/opt/openssl" +COPY --from=openssl-build ${openssl_prefix} ${openssl_prefix} +COPY --from=openssl-build /opt/cryptography/lib /usr/local/lib From d2affc3f8b831fcbb4d4ed5b5eec6320909e9928 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 14 Dec 2023 19:05:35 -0500 Subject: [PATCH 37/74] Update Dockerfile to be functional --- Dockerfile | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/Dockerfile b/Dockerfile index 98a1e1f..3d4435c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,31 +1,43 @@ +# syntax=docker/dockerfile:1 + # The official mitmproxy image uses OpenSSL 3.0.x, which has older versions of # the SSL and TLS protocols disabled. Unfortunately, the Wii U does not support -# the newer protocols, so we need to compile a custom version of OpenSSL that -# has the older protocols enabled and link it to the Python cryptography -# package. Then, we copy our build of OpenSSL and cryptography to the mitmproxy -# container. This is definitely a hack, but it seems to work. -FROM debian:bookworm AS openssl-build -ARG openssl_version="1.1.1w" openssl_prefix="/opt/openssl" openssl_dir="/usr/lib/ssl" +# newer protocols, so we need to compile a custom version of OpenSSL that has +# the older protocols enabled and link it to the Python cryptography package. +# Then, we copy our build of OpenSSL and cryptography to the final mitmproxy +# container. This is definitely a hack, but it seems to work fine in a container. + +ARG openssl_version="1.1.1w" openssl_dir="/opt/openssl" \ + openssl_config_dir="/usr/lib/ssl" cryptography_dir="/opt/cryptography" + +# We use the mitmproxy image for the build stage to ensure that all dependencies +# are at the right versions, even though mitmproxy itself is not used here. +FROM mitmproxy/mitmproxy:latest AS openssl-build +ARG openssl_version openssl_dir openssl_config_dir cryptography_dir # Install build dependencies RUN apt update -RUN apt install -y curl build-essential python3 python3-dev python3-pip python3-venv libffi-dev cargo pkg-config +RUN apt install -y curl build-essential libffi-dev pkg-config +RUN curl https://sh.rustup.rs | sh -s -- -y # Download and compile OpenSSL RUN curl https://www.openssl.org/source/openssl-${openssl_version}.tar.gz | tar -xvz -C /tmp WORKDIR /tmp/openssl-${openssl_version} -RUN ./config --prefix=${openssl_prefix} --openssldir=${openssl_dir} -Wl,-Bsymbolic-functions -fPIC shared +RUN ./config --prefix=${openssl_dir} --openssldir=${openssl_config_dir} -Wl,-Bsymbolic-functions -fPIC shared RUN make -j $(nproc) RUN make install_sw # Create Python cryptography environment -WORKDIR /opt -ENV OPENSSL_DIR=${openssl_prefix} -RUN python3 -m venv cryptography -RUN . ./cryptography/bin/activate && python3 -m pip install cryptography --no-binary cryptography +WORKDIR ${cryptography_dir} +ENV PATH="/root/.cargo/bin:${PATH}" +ENV OPENSSL_DIR=${openssl_dir} +RUN python3 -m venv venv +RUN . ${cryptography_dir}/venv/bin/activate && \ + python3 -m pip install cryptography --no-binary cryptography -v -# This is the main mitmproxy image that will be run +# This is the main mitmproxy container that will be run. We use a new image so +# the build tools are not left over in the final image. FROM mitmproxy/mitmproxy:latest AS mitmproxy -ARG openssl_prefix="/opt/openssl" -COPY --from=openssl-build ${openssl_prefix} ${openssl_prefix} -COPY --from=openssl-build /opt/cryptography/lib /usr/local/lib +ARG openssl_dir cryptography_dir +COPY --from=openssl-build ${openssl_dir} ${openssl_dir} +COPY --from=openssl-build ${cryptography_dir}/venv/lib /usr/local/lib From 33fde8aee269c80d63850cc333c1744490c7ce4c Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 14 Dec 2023 20:43:27 -0500 Subject: [PATCH 38/74] Use recommended apt order --- Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3d4435c..0aaf163 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,8 +16,9 @@ FROM mitmproxy/mitmproxy:latest AS openssl-build ARG openssl_version openssl_dir openssl_config_dir cryptography_dir # Install build dependencies -RUN apt update -RUN apt install -y curl build-essential libffi-dev pkg-config +RUN apt update && \ + apt install -y \ + curl build-essential libffi-dev pkg-config RUN curl https://sh.rustup.rs | sh -s -- -y # Download and compile OpenSSL From bfb5d01353ae9fbaa4dd27e20f7854a44bc3987f Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:25:56 -0500 Subject: [PATCH 39/74] Reconfigure mitmproxy for Docker --- .gitignore | 2 +- .mitmproxy | 1 + Dockerfile | 3 +++ configuration/config.yaml | 21 ++++----------------- 4 files changed, 9 insertions(+), 18 deletions(-) create mode 120000 .mitmproxy diff --git a/.gitignore b/.gitignore index d12df34..471d35b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ configuration/* !configuration/config.yaml # Python cache -__pycache__ \ No newline at end of file +__pycache__ diff --git a/.mitmproxy b/.mitmproxy new file mode 120000 index 0000000..7d0512e --- /dev/null +++ b/.mitmproxy @@ -0,0 +1 @@ +configuration/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 0aaf163..f0614b7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,3 +42,6 @@ FROM mitmproxy/mitmproxy:latest AS mitmproxy ARG openssl_dir cryptography_dir COPY --from=openssl-build ${openssl_dir} ${openssl_dir} COPY --from=openssl-build ${cryptography_dir}/venv/lib /usr/local/lib +WORKDIR /home/mitmproxy +COPY . . +EXPOSE 8080 8081 diff --git a/configuration/config.yaml b/configuration/config.yaml index 626e474..4cda7c6 100644 --- a/configuration/config.yaml +++ b/configuration/config.yaml @@ -1,25 +1,12 @@ # See https://docs.mitmproxy.org/stable/concepts-options/ for documentation -# An easy-to-remember port that should not conflict with anything -listen_port: 8888 -web_port: 8089 -mode: reverse:http://127.0.0.1:81 -keep_host_header: true -block_global: false +listen_port: 8080 +web_port: 8081 -# Disable HTTP/2 support, as it seems buggy and is not necessary -http2: false - -# These just make sure that the right configuration files and certs are loaded. +# This makes sure that the right configuration files and certs are loaded. client_certs: ./client-certificates/WiiU-common.pem confdir: ./configuration # This enables the Pretendo redirection script. -scripts: ["./pretendo_addon.py"] +scripts: ["../pretendo_addon.py"] pretendo_redirect: true - -# A couple convenience features -console_focus_follow: true -showhost: true -console_palette: dark -console_layout: vertical From d1f48199ba615dc85ea95ab7ff3152c665219107 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:40:20 -0500 Subject: [PATCH 40/74] Create Docker image build action --- .github/workflows/docker.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/docker.yml diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..e398931 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,24 @@ +name: Build Docker image + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Build the Docker image + run: docker build . --tag mitmproxy-pretendo + + - name: Save the Docker image + run: docker save mitmproxy-pretendo -o mitmproxy-pretendo.tar + + - name: Upload the Docker image + uses: actions/upload-artifact@v4 + with: + name: mitmproxy-pretendo-docker-image-${{ github.sha }} + path: mitmproxy-pretendo.tar From 1d253796b1c1c552c37be208c489570c7485ef36 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Fri, 15 Dec 2023 22:16:52 -0500 Subject: [PATCH 41/74] Set up the mitmproxy config as a symlink This allows the mitmproxy configuration directory to be saved as a Docker volume so that its certificates are not regenerated every time the container is run. If the config file is directly included in the volume, then new changes to it will not be copied over during the image build because the volume mount (which is using the old config version) overwrites the whole directory. Using a symlink allows modifying the config without modifying anything in the configuration directory. --- .gitignore | 9 ++++++--- .mitmproxy | 1 - .mitmproxy/config.yaml | 1 + launch | 2 +- configuration/config.yaml => mitmproxy-config.yaml | 6 +++--- 5 files changed, 11 insertions(+), 8 deletions(-) delete mode 120000 .mitmproxy create mode 120000 .mitmproxy/config.yaml rename configuration/config.yaml => mitmproxy-config.yaml (60%) diff --git a/.gitignore b/.gitignore index 471d35b..b107508 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ -# Files generated by mitmproxy but not the configuration -configuration/* -!configuration/config.yaml +# Files generated by mitmproxy, except for the main configuration +.mitmproxy/* +!.mitmproxy/config.yaml + +# Python virtual environment +/venv/ # Python cache __pycache__ diff --git a/.mitmproxy b/.mitmproxy deleted file mode 120000 index 7d0512e..0000000 --- a/.mitmproxy +++ /dev/null @@ -1 +0,0 @@ -configuration/ \ No newline at end of file diff --git a/.mitmproxy/config.yaml b/.mitmproxy/config.yaml new file mode 120000 index 0000000..8081b0b --- /dev/null +++ b/.mitmproxy/config.yaml @@ -0,0 +1 @@ +../mitmproxy-config.yaml \ No newline at end of file diff --git a/launch b/launch index 4c1bb0c..ade169e 100755 --- a/launch +++ b/launch @@ -1,4 +1,4 @@ #!/bin/bash cd "$(realpath --no-symlinks "$(dirname "$0")")" -$(basename "$0") --set confdir="./configuration" "$@" +$(basename "$0") --set confdir="./.mitmproxy" "$@" diff --git a/configuration/config.yaml b/mitmproxy-config.yaml similarity index 60% rename from configuration/config.yaml rename to mitmproxy-config.yaml index 4cda7c6..69c6c52 100644 --- a/configuration/config.yaml +++ b/mitmproxy-config.yaml @@ -3,10 +3,10 @@ listen_port: 8080 web_port: 8081 -# This makes sure that the right configuration files and certs are loaded. +# Make sure that the right configuration files and certs are loaded client_certs: ./client-certificates/WiiU-common.pem -confdir: ./configuration +confdir: ./.mitmproxy -# This enables the Pretendo redirection script. +# Enable the Pretendo redirection script scripts: ["../pretendo_addon.py"] pretendo_redirect: true From 29685194112b85556f054db561f35f6edd30abb4 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Fri, 15 Dec 2023 22:49:48 -0500 Subject: [PATCH 42/74] Add detailed usage instructions to the readme --- readme.md | 155 ++++++++++++++++++++++++++++++++++++++---------- start-docker.sh | 3 + 2 files changed, 127 insertions(+), 31 deletions(-) create mode 100755 start-docker.sh diff --git a/readme.md b/readme.md index 28df897..523ce0a 100644 --- a/readme.md +++ b/readme.md @@ -1,43 +1,136 @@ -# mitmproxy-nintedo +# Mitmproxy configuration for Pretendo -A package for intercepting traffic from the WiiU and 3DS +This repo contains configurations, scripts, and certificates for using +`mitmproxy`/`mitmweb`/`mitmdump` to intercept traffic from Nintendo consoles, +including the Wii U and the 3DS. This fork is designed to work with a local +Pretendo Network server. -## Prerequisites +## Usage -- mitmproxy (https://mitmproxy.org/) -- a *nix system (macos, linux, untested on WSL) -- SSL patches for your console ([3DS SSL Patch](https://github.com/InternalLoss/3DS-SSL-Patch), [WiiU SSL Patch](https://github.com/PretendoNetwork/Nimble/releases)) - - Alternatively, you can replace the `CACERT_NINTENDO_CA_G3.der` file with the mitmproxy CA cert. +### All setups -## Usage +1. Clone this repository to your computer + (`git clone https://github.com/MatthewL246/mitmproxy-pretendo.git`). +2. Choose a method below to run mitmproxy ([Docker](#running-with-docker) or + [local install](#running-locally)). +3. Install Pretendo Network patches on your console using + [the official guide](https://pretendo.network/docs/install): + - Download the patches for + [Wii U](https://github.com/PretendoNetwork/Inkay/releases) or + [3DS](https://github.com/PretendoNetwork/nimbus/releases). + - Skip creating a PNID on the official Pretendo server if you will be + hosting your own server. + - You'll need to recompile the patches with your custom certificate + ([see below](#compiling-custom-pretendo-patches)). +4. Configure your console to connect to the proxy using its system settings. Set + the console's proxy server to your computer's IP address and the port + to 8080. + +### Running with Docker + +This is the recommended way to run mitmproxy-pretendo because it always uses the +latest mitmproxy and is already set up with OpenSSL 1.1.1. + +1. Install Docker using the + [official instructions](https://docs.docker.com/get-docker/). +2. Run `docker build . -t mitmproxy-pretendo` to build the Docker image. This + will take a few minutes the first time, but it will be cached. +3. Start the Docker container by using the build `mitmproxy-pretendo` image. + - If you're not familiar with Docker, use this script to get started: + `./start-docker.sh`. Then, open in your browser + to access the `mitmweb` web interface for mitmproxy. + - Note that if you delete the `mitmproxy-pretendo-data` volume, the + mitmproxy server certificates will be regenerated and you will need to set + up the SSL patches with your custom certificates again. + +### Running locally + +This method can be used if you don't want to install Docker or just generally +perfer not using Docker. + +Note you may run into some issues depending your OpenSSL version. Many current +Linux distributions now use OpenSSL 3.0.0 instead of 1.1.1. OpenSSL 3.0.0 +disables protocols TLSv1.1 and earlier by default, but the console does not +support TLSv1.2 or later. Because of this, HTTPS connections to the proxy will +fail if mitmproxy is using OpenSSL 3.0.0. + +1. Install Python 3 and pip. +2. Create a virtual environment with `python3 -m venv venv`. +3. Activate the virtual environment with `. ./venv/bin/activate`. +4. Install [mitmproxy](https://mitmproxy.org/) with `pip install mitmproxy`. + - Test that mitmproxy is working by running `mitmproxy --version`. + - If the OpenSSL version is above 3.0.0, the console will fail to connect + via HTTPS. Consider using the Docker container instead, or compile a + custom version of OpenSSL and Python cryptography + ([see below](#using-a-custom-version-of-openssl-with-mitmproxy)). +5. Run one of the launcher scripts (i.e. `./mitmproxy`) to launch the mitmproxy + server. -- Clone this repo to your computer -- Run one of the launcher scripts to launch a proxy server -- Configure your console to connect to the proxy +Running the launcher script will now automatically load the Pretendo addon +script. This will add the custom `pretendo_redirect` and `pretendo_http` options +to mitmproxy. -Running the launcher script will now automatically load the Pretendo addon script. This will add the custom `pretendo_redirect` and `pretendo_http` options to mitmproxy. +## Modifications -### Replacing server certificates +### Compiling custom Pretendo patches -1. Back up all of your Wii U's certificates from `/storage_mlc/sys/title/0005001b/10054000/content`. This backup will be necessary to undo any modifications. -2. Convert your mitmproxy certificate to the right format by running the command `openssl x509 -in mitmproxy-ca-cert.pem -outform der -out CACERT_NINTENDO_CA_G3.der` in the `configuration` folder. -3. Upload the created `CACERT_NINTENDO_CA_G3.der` file to `/storage_mlc/sys/title/0005001b/10054000/content/scerts`, replacing the original file. +The Pretendo patches normally use a Let's Encrypt certificate for HTTPS +connections, but you can modify them to use your mitmproxy certificate instead. +Fortunately, it's pretty easy if you use Docker to compile the patches. -To undo this modification, just upload the backup files back to the `content` folder. +#### Wii U + +1. Clone the Inkay patcher + (`git clone https://github.com/PretendoNetwork/Inkay.git`) +2. Copy your mitmproxy certificate. + - If you're using the Docker container, run + `docker run -it -v mitmproxy-pretendo-data:/mnt busybox cat /mnt/mitmproxy-ca-cert.pem`. + - If you're running mitmproxy locally, run + `cat .mitmproxy/mitmproxy-ca-cert.pem`. +3. Replace the contents of `./Inkay/data/ca.pem` with your mitmproxy + certificate. +4. Run `docker build Inkay -t inkay-build` to build the Inkay build environment. +5. Run `docker run -it --rm -v $(pwd)/Inkay:/app -w /app inkay-build` to compile + the patches. +6. The compiled patch will be in `./Inkay/Inkay-pretendo.wps`. Copy this patch + to your SD card at `sd:/wiiu/environments/aroma/plugins`, replacing the + Pretendo patch that is already there. + +Due to Inkay's dependencies, it would be quite difficult to compile the patches +without using Docker. If you don't want to install Docker, you could try forking +the Inkay repository on GitHub, editing the `data/ca.pem` file in your fork, and +building it with GitHub Actions. + +#### 3DS + +I don't think that the 3DS patches support custom certificates because they just +disable all certificate checks, but I haven't tested this. ### Using a custom version of OpenSSL with mitmproxy -1. Install mitmproxy normally with `pip install mitmproxy`. -2. Get the [latest version](https://www.openssl.org/source/) of **OpenSSL 1.1.1** and download it with `curl https://www.openssl.org/source/openssl-1.1.1(version).tar.gz | tar xz; cd openssl-1.1.1(version)` -3. Compile OpenSSL and Python cryptography according to the [Python cryptography module documentation](https://cryptography.io/en/latest/installation/#build-on-linux): -``` -sudo apt-get install build-essential libffi-dev python3-dev cargo -y -sudo apt-get remove libssl-dev -y -./config -Wl,-Bsymbolic-functions -fPIC shared -sudo make -j8 -sudo make install_sw -openssl version -hash -r -pip install cryptography --no-binary cryptography --force -``` -Running `mitmproxy --version` should now show the custom version of OpenSSL. +See the [Dockerfile](./Dockerfile) for the necessary build steps. If you are +doing this on your primary system, be very careful to not mess with your system +package manager's OpenSSL installation, as this would break everything that +relies on OpenSSL. Make sure you use a custom prefix like `/opt/openssl` when +compiling OpenSSL 1.1.1. Use the steps to install a custom build of Python +cryptography in your mitmproxy virtual environment. + +### Permanently replacing server certificates + +If you want to intercept your console's HTTPS traffic with mitmproxy all the +time without using the Pretendo patches, you will need to replace your console's +server certificate with the mitmproxy certificate. Note that this is somewhat +dangerous, as a corrupted certificate can brick your Home Menu. This should be +safe using a coldboot CFW like CHBC, Tiramisu, or Aroma, but be aware of the +risk. + +1. Back up all of your Wii U's certificates from + `/storage_mlc/sys/title/0005001b/10054000/content`. This backup will be + necessary to undo any modifications. +2. Convert your mitmproxy certificate to the right format by running the command + `openssl x509 -in ./configuration/mitmproxy-ca-cert.pem -outform der -out CACERT_NINTENDO_CA_G3.der`. +3. Upload the created `CACERT_NINTENDO_CA_G3.der` file to + `/storage_mlc/sys/title/0005001b/10054000/content/scerts`, replacing the + original file. + +To undo this modification, upload the backup files back to the `content` folder. diff --git a/start-docker.sh b/start-docker.sh new file mode 100755 index 0000000..e7b1504 --- /dev/null +++ b/start-docker.sh @@ -0,0 +1,3 @@ +#! /bin/sh + +docker run -it --rm -v mitmproxy-pretendo-data:/home/mitmproxy/.mitmproxy -p 8080:8080 -p 127.0.0.1:8081:8081 mitmproxy-pretendo mitmweb --web-host 0.0.0.0 From 6f7453a1735c0077ff634d3d0a5d599f67f4a55e Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sat, 16 Dec 2023 14:51:10 -0500 Subject: [PATCH 43/74] Set up Docker publish to GHCR --- .github/workflows/docker.yml | 40 ++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index e398931..1380b95 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,24 +1,42 @@ -name: Build Docker image +name: Build and Publish Docker Image on: push: pull_request: + workflow_dispatch: jobs: - build: + build-publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 - - name: Build the Docker image - run: docker build . --tag mitmproxy-pretendo + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - - name: Save the Docker image - run: docker save mitmproxy-pretendo -o mitmproxy-pretendo.tar + - name: Log into the GitHub container registry + if: ${{ github.event != 'pull_request' && github.ref == 'refs/heads/main' }} + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} - - name: Upload the Docker image - uses: actions/upload-artifact@v4 + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@v5 with: - name: mitmproxy-pretendo-docker-image-${{ github.sha }} - path: mitmproxy-pretendo.tar + context: . + push: ${{ github.event != 'pull_request' && github.ref == 'refs/heads/main' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max From a2d6a34d5a9dc4480169300fc64c4ed7bf71315c Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sat, 16 Dec 2023 14:55:45 -0500 Subject: [PATCH 44/74] Create dependabot.yml --- .github/dependabot.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..1c4864e --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + assignees: + - MatthewL246 From 653acb3d01ba7c7251cae0e43bfc13616ac163e7 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sat, 16 Dec 2023 15:05:30 -0500 Subject: [PATCH 45/74] Create .dockerignore --- .dockerignore | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f961d37 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +# Git and GitHub files +/.git/ +/.github/ + +# Local Python environment +/venv/ +*__pycache__* From f9b75051655b60c30b7728b9fc689dd49067b101 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sat, 16 Dec 2023 15:10:25 -0500 Subject: [PATCH 46/74] Enable Docker latest tag --- .github/workflows/docker.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 1380b95..396f867 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -29,6 +29,7 @@ jobs: uses: docker/metadata-action@v5 with: images: ghcr.io/${{ github.repository }} + flavor: latest=true - name: Build and push Docker image id: build-and-push From ceab5c54b7d0b5c6711d5be0b5bcb609f2e60ff9 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sat, 16 Dec 2023 15:43:11 -0500 Subject: [PATCH 47/74] Update the readme with instructions for the published image --- .gitignore | 4 +-- readme.md => README.md | 70 ++++++++++++++++++++++++++---------------- start-docker.sh | 3 +- 3 files changed, 48 insertions(+), 29 deletions(-) rename readme.md => README.md (76%) diff --git a/.gitignore b/.gitignore index b107508..6d62816 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # Files generated by mitmproxy, except for the main configuration -.mitmproxy/* -!.mitmproxy/config.yaml +/.mitmproxy/ +!/.mitmproxy/config.yaml # Python virtual environment /venv/ diff --git a/readme.md b/README.md similarity index 76% rename from readme.md rename to README.md index 523ce0a..b4c07db 100644 --- a/readme.md +++ b/README.md @@ -9,40 +9,41 @@ Pretendo Network server. ### All setups -1. Clone this repository to your computer - (`git clone https://github.com/MatthewL246/mitmproxy-pretendo.git`). -2. Choose a method below to run mitmproxy ([Docker](#running-with-docker) or +1. Choose a method below to run mitmproxy ([Docker](#running-with-docker) or [local install](#running-locally)). -3. Install Pretendo Network patches on your console using - [the official guide](https://pretendo.network/docs/install): - - Download the patches for - [Wii U](https://github.com/PretendoNetwork/Inkay/releases) or - [3DS](https://github.com/PretendoNetwork/nimbus/releases). - - Skip creating a PNID on the official Pretendo server if you will be - hosting your own server. - - You'll need to recompile the patches with your custom certificate - ([see below](#compiling-custom-pretendo-patches)). -4. Configure your console to connect to the proxy using its system settings. Set - the console's proxy server to your computer's IP address and the port - to 8080. +2. Set up your console to connect the the proxy ([see below](#console-setup)). ### Running with Docker This is the recommended way to run mitmproxy-pretendo because it always uses the -latest mitmproxy and is already set up with OpenSSL 1.1.1. +latest image and is already set up with OpenSSL 1.1.1. 1. Install Docker using the [official instructions](https://docs.docker.com/get-docker/). -2. Run `docker build . -t mitmproxy-pretendo` to build the Docker image. This - will take a few minutes the first time, but it will be cached. -3. Start the Docker container by using the build `mitmproxy-pretendo` image. - - If you're not familiar with Docker, use this script to get started: - `./start-docker.sh`. Then, open in your browser - to access the `mitmweb` web interface for mitmproxy. +2. Run a new Docker container using the `ghcr.io/matthewl246/mitmproxy-pretendo` + image. + - If you're not familiar with Docker, copy the `docker run ...` command from + [this script](./start-docker.sh) to get started. Then, open + in your browser to access the `mitmweb` web + interface for mitmproxy. - Note that if you delete the `mitmproxy-pretendo-data` volume, the mitmproxy server certificates will be regenerated and you will need to set up the SSL patches with your custom certificates again. +#### Rebuilding the Docker image + +If you want to make modifications to the image, you need to rebuild it locally. + +1. Clone this repository to your computer + (`git clone https://github.com/MatthewL246/mitmproxy-pretendo.git`). +2. Use the `./start-docker.sh` script to build and run the container. This build + overwrites the version you downloaded from the container registry. This will + take a few minutes the first time, but it will be cached for future builds. + - You need to rebuild the container every time you change something here. + +If you want to revert your local image to the published version, run +`docker pull ghcr.io/matthewl246/mitmproxy-pretendo`. + ### Running locally This method can be used if you don't want to install Docker or just generally @@ -55,21 +56,38 @@ support TLSv1.2 or later. Because of this, HTTPS connections to the proxy will fail if mitmproxy is using OpenSSL 3.0.0. 1. Install Python 3 and pip. -2. Create a virtual environment with `python3 -m venv venv`. -3. Activate the virtual environment with `. ./venv/bin/activate`. -4. Install [mitmproxy](https://mitmproxy.org/) with `pip install mitmproxy`. +2. Clone this repository to your computer + (`git clone https://github.com/MatthewL246/mitmproxy-pretendo.git`). +3. Create a virtual environment with `python3 -m venv venv`. +4. Activate the virtual environment with `. ./venv/bin/activate`. +5. Install [mitmproxy](https://mitmproxy.org/) with `pip install mitmproxy`. - Test that mitmproxy is working by running `mitmproxy --version`. - If the OpenSSL version is above 3.0.0, the console will fail to connect via HTTPS. Consider using the Docker container instead, or compile a custom version of OpenSSL and Python cryptography ([see below](#using-a-custom-version-of-openssl-with-mitmproxy)). -5. Run one of the launcher scripts (i.e. `./mitmproxy`) to launch the mitmproxy +6. Run one of the launcher scripts (i.e. `./mitmproxy`) to launch the mitmproxy server. Running the launcher script will now automatically load the Pretendo addon script. This will add the custom `pretendo_redirect` and `pretendo_http` options to mitmproxy. +## Console setup + +1. Install Pretendo Network patches on your console using + [the official guide](https://pretendo.network/docs/install): + - Download the patches for + [Wii U](https://github.com/PretendoNetwork/Inkay/releases) or + [3DS](https://github.com/PretendoNetwork/nimbus/releases). + - Skip creating a PNID on the official Pretendo server if you will be + hosting your own server. + - You'll now need to recompile the patches with your custom certificate + ([see below](#compiling-custom-pretendo-patches)). +2. Configure your console to connect to the proxy using its system settings. Set + the console's proxy server to your computer's IP address and the port + to 8080. + ## Modifications ### Compiling custom Pretendo patches diff --git a/start-docker.sh b/start-docker.sh index e7b1504..10eb790 100755 --- a/start-docker.sh +++ b/start-docker.sh @@ -1,3 +1,4 @@ #! /bin/sh -docker run -it --rm -v mitmproxy-pretendo-data:/home/mitmproxy/.mitmproxy -p 8080:8080 -p 127.0.0.1:8081:8081 mitmproxy-pretendo mitmweb --web-host 0.0.0.0 +docker build . -t ghcr.io/matthewl246/mitmproxy-pretendo +docker run -it --rm -v mitmproxy-pretendo-data:/home/mitmproxy/.mitmproxy -p 8080:8080 -p 127.0.0.1:8081:8081 ghcr.io/matthewl246/mitmproxy-pretendo mitmweb --web-host 0.0.0.0 From 25ff8d1cb262c6980932cd404f5d5d2b7e4bf6a6 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sat, 16 Dec 2023 15:58:00 -0500 Subject: [PATCH 48/74] Name the container --- start-docker.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/start-docker.sh b/start-docker.sh index 10eb790..49f30c4 100755 --- a/start-docker.sh +++ b/start-docker.sh @@ -1,4 +1,4 @@ #! /bin/sh docker build . -t ghcr.io/matthewl246/mitmproxy-pretendo -docker run -it --rm -v mitmproxy-pretendo-data:/home/mitmproxy/.mitmproxy -p 8080:8080 -p 127.0.0.1:8081:8081 ghcr.io/matthewl246/mitmproxy-pretendo mitmweb --web-host 0.0.0.0 +docker run -it --rm --name mitmproxy-pretendo -v mitmproxy-pretendo-data:/home/mitmproxy/.mitmproxy -p 8080:8080 -p 127.0.0.1:8081:8081 ghcr.io/matthewl246/mitmproxy-pretendo mitmweb --web-host 0.0.0.0 From 85b7d1e4a88e937bce5dc6e6dc9d2d1f6aacaa93 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sat, 16 Dec 2023 16:17:12 -0500 Subject: [PATCH 49/74] Update information on custom Pretendo patches --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b4c07db..86c39db 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,8 @@ to mitmproxy. [3DS](https://github.com/PretendoNetwork/nimbus/releases). - Skip creating a PNID on the official Pretendo server if you will be hosting your own server. - - You'll now need to recompile the patches with your custom certificate + - If you want to use Justaposition, you'll now need to recompile the patches + with your custom certificate ([see below](#compiling-custom-pretendo-patches)). 2. Configure your console to connect to the proxy using its system settings. Set the console's proxy server to your computer's IP address and the port @@ -111,14 +112,20 @@ Fortunately, it's pretty easy if you use Docker to compile the patches. 5. Run `docker run -it --rm -v $(pwd)/Inkay:/app -w /app inkay-build` to compile the patches. 6. The compiled patch will be in `./Inkay/Inkay-pretendo.wps`. Copy this patch - to your SD card at `sd:/wiiu/environments/aroma/plugins`, replacing the - Pretendo patch that is already there. + to your SD card over FTPiiU by running + `ftp -u ftp://a:a@WIIU_IP/fs/vol/external01/wiiu/environments/aroma/plugins/Inkay-pretendo.wps ./Inkay/Inkay-pretendo.wps`, + replacing the `WIIU_IP` with your Wii U's IP address. This will replace the + Pretendo patch with your version with custom certificates. +7. Reboot your Wii U. Due to Inkay's dependencies, it would be quite difficult to compile the patches without using Docker. If you don't want to install Docker, you could try forking the Inkay repository on GitHub, editing the `data/ca.pem` file in your fork, and building it with GitHub Actions. +If you want to revert back to the regular Pretendo Network patches, redownload +them from the Inkay repository and upload them back to your Wii U. + #### 3DS I don't think that the 3DS patches support custom certificates because they just From 57e18cf0fbe33d4a60c3da505b7a0ea125d20bb9 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sat, 16 Dec 2023 16:35:30 -0500 Subject: [PATCH 50/74] Set up a configuration that works on Wii U --- mitmproxy-config.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mitmproxy-config.yaml b/mitmproxy-config.yaml index 69c6c52..b9a4877 100644 --- a/mitmproxy-config.yaml +++ b/mitmproxy-config.yaml @@ -10,3 +10,14 @@ confdir: ./.mitmproxy # Enable the Pretendo redirection script scripts: ["../pretendo_addon.py"] pretendo_redirect: true + +# Allow self-signed certificates +ssl_insecure: true + +# Allow the console to use older TLS versions +tls_version_client_min: UNBOUNDED +tls_version_server_min: UNBOUNDED + +# A few convenience features +anticache: true +showhost: true From 2cc396b8bba7876574c16b155154e57c9f350123 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sat, 16 Dec 2023 16:41:01 -0500 Subject: [PATCH 51/74] Delete the temporary container when compiling custom patches --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 86c39db..8803b33 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ Fortunately, it's pretty easy if you use Docker to compile the patches. (`git clone https://github.com/PretendoNetwork/Inkay.git`) 2. Copy your mitmproxy certificate. - If you're using the Docker container, run - `docker run -it -v mitmproxy-pretendo-data:/mnt busybox cat /mnt/mitmproxy-ca-cert.pem`. + `docker run -it --rm -v mitmproxy-pretendo-data:/mnt busybox cat /mnt/mitmproxy-ca-cert.pem`. - If you're running mitmproxy locally, run `cat .mitmproxy/mitmproxy-ca-cert.pem`. 3. Replace the contents of `./Inkay/data/ca.pem` with your mitmproxy From adeacbb57efd9b6751acde57021c71fda27c6671 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sat, 16 Dec 2023 18:38:11 -0500 Subject: [PATCH 52/74] Reformat YAML --- .github/dependabot.yml | 12 +++---- .github/workflows/docker.yml | 70 +++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1c4864e..672fc27 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,8 @@ version: 2 updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: daily - assignees: - - MatthewL246 + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + assignees: + - MatthewL246 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 396f867..aa527af 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,43 +1,47 @@ name: Build and Publish Docker Image on: - push: - pull_request: - workflow_dispatch: + push: + pull_request: + workflow_dispatch: jobs: - build-publish: - runs-on: ubuntu-latest + build-publish: + runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 + steps: + - name: Checkout repository + uses: actions/checkout@v4 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - - name: Log into the GitHub container registry - if: ${{ github.event != 'pull_request' && github.ref == 'refs/heads/main' }} - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + - name: Log into the GitHub container registry + if: + ${{ github.event != 'pull_request' && github.ref == + 'refs/heads/main' }} + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ghcr.io/${{ github.repository }} - flavor: latest=true + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + flavor: latest=true - - name: Build and push Docker image - id: build-and-push - uses: docker/build-push-action@v5 - with: - context: . - push: ${{ github.event != 'pull_request' && github.ref == 'refs/heads/main' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@v5 + with: + context: . + push: + ${{ github.event != 'pull_request' && github.ref == + 'refs/heads/main' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max From 7a20b5e6d9c0fa77b579959145d1c4e30bdab9f6 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sun, 17 Dec 2023 14:24:42 -0500 Subject: [PATCH 53/74] Set up script for custom Pretendo hosts --- pretendo_addon.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/pretendo_addon.py b/pretendo_addon.py index f81631e..1271c55 100644 --- a/pretendo_addon.py +++ b/pretendo_addon.py @@ -17,14 +17,33 @@ def load(self, loader) -> None: help="Sets Pretendo requests to HTTP", ) + loader.add_option( + name="pretendo_host", + typespec=str, + default="pretendo.cc", + help="Host to send Pretendo requests to (keeps the original host in the Host header)", + ) + + loader.add_option( + name="pretendo_host_port", + typespec=int, + default=80, + help="Port to send Pretendo requests to", + ) + def request(self, flow: http.HTTPFlow) -> None: if ctx.options.pretendo_redirect: if 'nintendo.net' in flow.request.pretty_host: - flow.request.host_header = flow.request.pretty_host.replace('nintendo.net', 'pretendo.cc') + flow.request.host = flow.request.pretty_host.replace('nintendo.net', 'pretendo.cc') elif 'nintendowifi.net' in flow.request.pretty_host: - flow.request.host_header = flow.request.pretty_host.replace('nintendowifi.net', 'pretendo.cc') - elif 'rverse.club' in flow.request.pretty_host: - flow.request.host_header = flow.request.pretty_host.replace('rverse.club', 'pretendo.cc') + flow.request.host = flow.request.pretty_host.replace('nintendowifi.net', 'pretendo.cc') + + if 'pretendo.cc' in flow.request.pretty_host: + flow.request.port = ctx.options.pretendo_host_port + + original_host = flow.request.host_header + flow.request.host = ctx.options.pretendo_host + flow.request.host_header = original_host if ctx.options.pretendo_http: flow.request.scheme = 'http' From d8ec9c9ea57d8133e278b6d5330d26e25aa19939 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Sun, 17 Dec 2023 20:35:16 -0500 Subject: [PATCH 54/74] Fix usage without a custom host --- pretendo_addon.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pretendo_addon.py b/pretendo_addon.py index 1271c55..11577ed 100644 --- a/pretendo_addon.py +++ b/pretendo_addon.py @@ -10,25 +10,25 @@ def load(self, loader) -> None: help="Redirect all requests from Nintendo to Pretendo", ) - loader.add_option( - name="pretendo_http", - typespec=bool, - default=False, - help="Sets Pretendo requests to HTTP", - ) - loader.add_option( name="pretendo_host", typespec=str, - default="pretendo.cc", + default="", help="Host to send Pretendo requests to (keeps the original host in the Host header)", ) + loader.add_option( + name="pretendo_http", + typespec=bool, + default=False, + help="Sets Pretendo requests to HTTP (only applies if pretendo_host is set)", + ) + loader.add_option( name="pretendo_host_port", typespec=int, default=80, - help="Port to send Pretendo requests to", + help="Port to send Pretendo requests to (only applies if pretendo_host is set)", ) def request(self, flow: http.HTTPFlow) -> None: @@ -38,14 +38,14 @@ def request(self, flow: http.HTTPFlow) -> None: elif 'nintendowifi.net' in flow.request.pretty_host: flow.request.host = flow.request.pretty_host.replace('nintendowifi.net', 'pretendo.cc') - if 'pretendo.cc' in flow.request.pretty_host: - flow.request.port = ctx.options.pretendo_host_port - + if 'pretendo.cc' in flow.request.pretty_host and ctx.options.pretendo_host: original_host = flow.request.host_header flow.request.host = ctx.options.pretendo_host flow.request.host_header = original_host - if ctx.options.pretendo_http: - flow.request.scheme = 'http' + flow.request.port = ctx.options.pretendo_host_port + + if ctx.options.pretendo_http: + flow.request.scheme = 'http' addons = [PretendoAddon()] From b0789f111faf8901855d1863d3875a300999565f Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Mon, 18 Dec 2023 16:59:37 -0500 Subject: [PATCH 55/74] Fix the host redirection Apparently, changing the port also changes the Host header. --- pretendo_addon.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pretendo_addon.py b/pretendo_addon.py index 11577ed..7304fdb 100644 --- a/pretendo_addon.py +++ b/pretendo_addon.py @@ -41,9 +41,8 @@ def request(self, flow: http.HTTPFlow) -> None: if 'pretendo.cc' in flow.request.pretty_host and ctx.options.pretendo_host: original_host = flow.request.host_header flow.request.host = ctx.options.pretendo_host - flow.request.host_header = original_host - flow.request.port = ctx.options.pretendo_host_port + flow.request.host_header = original_host if ctx.options.pretendo_http: flow.request.scheme = 'http' From 2d05ef8c66cec1413d4c1987c0780a23b34cf778 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Mon, 18 Dec 2023 17:42:43 -0500 Subject: [PATCH 56/74] Add support for pretendo.network and reformat (they hardcoded the website cookie domains) --- pretendo_addon.py | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/pretendo_addon.py b/pretendo_addon.py index 7304fdb..fbfe8d0 100644 --- a/pretendo_addon.py +++ b/pretendo_addon.py @@ -6,7 +6,7 @@ def load(self, loader) -> None: loader.add_option( name="pretendo_redirect", typespec=bool, - default=False, + default=True, help="Redirect all requests from Nintendo to Pretendo", ) @@ -17,13 +17,6 @@ def load(self, loader) -> None: help="Host to send Pretendo requests to (keeps the original host in the Host header)", ) - loader.add_option( - name="pretendo_http", - typespec=bool, - default=False, - help="Sets Pretendo requests to HTTP (only applies if pretendo_host is set)", - ) - loader.add_option( name="pretendo_host_port", typespec=int, @@ -31,20 +24,35 @@ def load(self, loader) -> None: help="Port to send Pretendo requests to (only applies if pretendo_host is set)", ) + loader.add_option( + name="pretendo_http", + typespec=bool, + default=False, + help="Sets Pretendo requests to HTTP (only applies if pretendo_host is set)", + ) + def request(self, flow: http.HTTPFlow) -> None: if ctx.options.pretendo_redirect: - if 'nintendo.net' in flow.request.pretty_host: - flow.request.host = flow.request.pretty_host.replace('nintendo.net', 'pretendo.cc') - elif 'nintendowifi.net' in flow.request.pretty_host: - flow.request.host = flow.request.pretty_host.replace('nintendowifi.net', 'pretendo.cc') - - if 'pretendo.cc' in flow.request.pretty_host and ctx.options.pretendo_host: + if "nintendo.net" in flow.request.pretty_host: + flow.request.host = flow.request.pretty_host.replace( + "nintendo.net", "pretendo.cc" + ) + elif "nintendowifi.net" in flow.request.pretty_host: + flow.request.host = flow.request.pretty_host.replace( + "nintendowifi.net", "pretendo.cc" + ) + + if ctx.options.pretendo_host and ( + "pretendo.cc" in flow.request.pretty_host + or "pretendo.network" in flow.request.pretty_host + ): original_host = flow.request.host_header flow.request.host = ctx.options.pretendo_host flow.request.port = ctx.options.pretendo_host_port flow.request.host_header = original_host if ctx.options.pretendo_http: - flow.request.scheme = 'http' + flow.request.scheme = "http" + addons = [PretendoAddon()] From 40c73218c970778811542c12061e7a8b6c627ee2 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:08:15 -0500 Subject: [PATCH 57/74] Add Pretendo's hard-coded CDN to redirects --- pretendo_addon.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pretendo_addon.py b/pretendo_addon.py index fbfe8d0..33a3ca1 100644 --- a/pretendo_addon.py +++ b/pretendo_addon.py @@ -45,6 +45,7 @@ def request(self, flow: http.HTTPFlow) -> None: if ctx.options.pretendo_host and ( "pretendo.cc" in flow.request.pretty_host or "pretendo.network" in flow.request.pretty_host + or "pretendo-cdn.b-cdn.net" in flow.request.pretty_host ): original_host = flow.request.host_header flow.request.host = ctx.options.pretendo_host From a10fa93bdb12641d4578cdab7442ebe37b29061f Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Tue, 26 Dec 2023 21:13:51 -0500 Subject: [PATCH 58/74] Fix formatting issues caused by bad Prettier config --- .github/dependabot.yml | 12 +++--- .github/workflows/docker.yml | 73 ++++++++++++++++++------------------ README.md | 50 ++++++++++++------------ 3 files changed, 67 insertions(+), 68 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 672fc27..1c4864e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,8 @@ version: 2 updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: daily - assignees: - - MatthewL246 + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + assignees: + - MatthewL246 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index aa527af..d2560ce 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,47 +1,46 @@ name: Build and Publish Docker Image on: - push: - pull_request: - workflow_dispatch: + push: + pull_request: + workflow_dispatch: jobs: - build-publish: - runs-on: ubuntu-latest + build-publish: + runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 + steps: + - name: Checkout repository + uses: actions/checkout@v4 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - - name: Log into the GitHub container registry - if: - ${{ github.event != 'pull_request' && github.ref == - 'refs/heads/main' }} - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + - name: Log into the GitHub container registry + if: + ${{ github.event != 'pull_request' && github.ref == 'refs/heads/main' }} + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ghcr.io/${{ github.repository }} - flavor: latest=true + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + flavor: latest=true - - name: Build and push Docker image - id: build-and-push - uses: docker/build-push-action@v5 - with: - context: . - push: - ${{ github.event != 'pull_request' && github.ref == - 'refs/heads/main' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@v5 + with: + context: . + push: + ${{ github.event != 'pull_request' && github.ref == + 'refs/heads/main' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/README.md b/README.md index 8803b33..e676be6 100644 --- a/README.md +++ b/README.md @@ -22,13 +22,13 @@ latest image and is already set up with OpenSSL 1.1.1. [official instructions](https://docs.docker.com/get-docker/). 2. Run a new Docker container using the `ghcr.io/matthewl246/mitmproxy-pretendo` image. - - If you're not familiar with Docker, copy the `docker run ...` command from - [this script](./start-docker.sh) to get started. Then, open - in your browser to access the `mitmweb` web - interface for mitmproxy. - - Note that if you delete the `mitmproxy-pretendo-data` volume, the - mitmproxy server certificates will be regenerated and you will need to set - up the SSL patches with your custom certificates again. + - If you're not familiar with Docker, copy the `docker run ...` command from + [this script](./start-docker.sh) to get started. Then, open + in your browser to access the `mitmweb` web + interface for mitmproxy. + - Note that if you delete the `mitmproxy-pretendo-data` volume, the mitmproxy + server certificates will be regenerated and you will need to set up the SSL + patches with your custom certificates again. #### Rebuilding the Docker image @@ -39,7 +39,7 @@ If you want to make modifications to the image, you need to rebuild it locally. 2. Use the `./start-docker.sh` script to build and run the container. This build overwrites the version you downloaded from the container registry. This will take a few minutes the first time, but it will be cached for future builds. - - You need to rebuild the container every time you change something here. + - You need to rebuild the container every time you change something here. If you want to revert your local image to the published version, run `docker pull ghcr.io/matthewl246/mitmproxy-pretendo`. @@ -61,11 +61,11 @@ fail if mitmproxy is using OpenSSL 3.0.0. 3. Create a virtual environment with `python3 -m venv venv`. 4. Activate the virtual environment with `. ./venv/bin/activate`. 5. Install [mitmproxy](https://mitmproxy.org/) with `pip install mitmproxy`. - - Test that mitmproxy is working by running `mitmproxy --version`. - - If the OpenSSL version is above 3.0.0, the console will fail to connect - via HTTPS. Consider using the Docker container instead, or compile a - custom version of OpenSSL and Python cryptography - ([see below](#using-a-custom-version-of-openssl-with-mitmproxy)). + - Test that mitmproxy is working by running `mitmproxy --version`. + - If the OpenSSL version is above 3.0.0, the console will fail to connect via + HTTPS. Consider using the Docker container instead, or compile a custom + version of OpenSSL and Python cryptography + ([see below](#using-a-custom-version-of-openssl-with-mitmproxy)). 6. Run one of the launcher scripts (i.e. `./mitmproxy`) to launch the mitmproxy server. @@ -77,14 +77,14 @@ to mitmproxy. 1. Install Pretendo Network patches on your console using [the official guide](https://pretendo.network/docs/install): - - Download the patches for - [Wii U](https://github.com/PretendoNetwork/Inkay/releases) or - [3DS](https://github.com/PretendoNetwork/nimbus/releases). - - Skip creating a PNID on the official Pretendo server if you will be - hosting your own server. - - If you want to use Justaposition, you'll now need to recompile the patches - with your custom certificate - ([see below](#compiling-custom-pretendo-patches)). + - Download the patches for + [Wii U](https://github.com/PretendoNetwork/Inkay/releases) or + [3DS](https://github.com/PretendoNetwork/nimbus/releases). + - Skip creating a PNID on the official Pretendo server if you will be hosting + your own server. + - If you want to use Justaposition, you'll now need to recompile the patches + with your custom certificate + ([see below](#compiling-custom-pretendo-patches)). 2. Configure your console to connect to the proxy using its system settings. Set the console's proxy server to your computer's IP address and the port to 8080. @@ -102,10 +102,10 @@ Fortunately, it's pretty easy if you use Docker to compile the patches. 1. Clone the Inkay patcher (`git clone https://github.com/PretendoNetwork/Inkay.git`) 2. Copy your mitmproxy certificate. - - If you're using the Docker container, run - `docker run -it --rm -v mitmproxy-pretendo-data:/mnt busybox cat /mnt/mitmproxy-ca-cert.pem`. - - If you're running mitmproxy locally, run - `cat .mitmproxy/mitmproxy-ca-cert.pem`. + - If you're using the Docker container, run + `docker run -it --rm -v mitmproxy-pretendo-data:/mnt busybox cat /mnt/mitmproxy-ca-cert.pem`. + - If you're running mitmproxy locally, run + `cat .mitmproxy/mitmproxy-ca-cert.pem`. 3. Replace the contents of `./Inkay/data/ca.pem` with your mitmproxy certificate. 4. Run `docker build Inkay -t inkay-build` to build the Inkay build environment. From 4803b3a097cb5a14f0fc97e373c0a9c63c3e46a4 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Tue, 2 Jan 2024 22:56:06 -0500 Subject: [PATCH 59/74] Add 3DS instructions and fix a few typos --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e676be6..fdb0ac5 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ If you want to revert your local image to the published version, run ### Running locally This method can be used if you don't want to install Docker or just generally -perfer not using Docker. +prefer not to use Docker. Note you may run into some issues depending your OpenSSL version. Many current Linux distributions now use OpenSSL 3.0.0 instead of 1.1.1. OpenSSL 3.0.0 @@ -82,7 +82,7 @@ to mitmproxy. [3DS](https://github.com/PretendoNetwork/nimbus/releases). - Skip creating a PNID on the official Pretendo server if you will be hosting your own server. - - If you want to use Justaposition, you'll now need to recompile the patches + - If you want to use Juxtaposition, you'll now need to recompile the patches with your custom certificate ([see below](#compiling-custom-pretendo-patches)). 2. Configure your console to connect to the proxy using its system settings. Set @@ -123,13 +123,13 @@ without using Docker. If you don't want to install Docker, you could try forking the Inkay repository on GitHub, editing the `data/ca.pem` file in your fork, and building it with GitHub Actions. -If you want to revert back to the regular Pretendo Network patches, redownload +If you want to revert back to the regular Pretendo Network patches, re-download them from the Inkay repository and upload them back to your Wii U. #### 3DS -I don't think that the 3DS patches support custom certificates because they just -disable all certificate checks, but I haven't tested this. +Copy the `mitmproxy-ca-cert.pem` file to your microSD card as +`sd:/3ds/juxt-prod.pem`. ### Using a custom version of OpenSSL with mitmproxy From 293ece3ddeaa30c7dc453f4dbef911aeee6bbf3e Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 4 Jan 2024 08:09:29 -0500 Subject: [PATCH 60/74] Enable local server redirection by default --- mitmproxy-config.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mitmproxy-config.yaml b/mitmproxy-config.yaml index b9a4877..c9fec0c 100644 --- a/mitmproxy-config.yaml +++ b/mitmproxy-config.yaml @@ -11,6 +11,11 @@ confdir: ./.mitmproxy scripts: ["../pretendo_addon.py"] pretendo_redirect: true +# Set up redirection to a local server +pretendo_host: nginx +pretendo_host_port: 80 +pretendo_http: true + # Allow self-signed certificates ssl_insecure: true From 6f9aa93ffb4472a9c3b18ee6b5f5aa222f5528ec Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 4 Jan 2024 08:16:27 -0500 Subject: [PATCH 61/74] Set up the network dump configurations --- .mitmproxy/config.yaml | 2 +- config-3ds.yaml | 9 +++++++++ mitmproxy-config.yaml => config-local.yaml | 0 config-wiiu.yaml | 9 +++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 config-3ds.yaml rename mitmproxy-config.yaml => config-local.yaml (100%) create mode 100644 config-wiiu.yaml diff --git a/.mitmproxy/config.yaml b/.mitmproxy/config.yaml index 8081b0b..46a5321 120000 --- a/.mitmproxy/config.yaml +++ b/.mitmproxy/config.yaml @@ -1 +1 @@ -../mitmproxy-config.yaml \ No newline at end of file +../config-local.yaml \ No newline at end of file diff --git a/config-3ds.yaml b/config-3ds.yaml new file mode 100644 index 0000000..a8e02f1 --- /dev/null +++ b/config-3ds.yaml @@ -0,0 +1,9 @@ +listen_port: 8083 +web_port: 8081 + +hardump: ./pretendo-network-dump-3ds.har + +client_certs: ./client-certificates/CTR-common.pem +ssl_insecure: true +tls_version_client_min: UNBOUNDED +tls_version_server_min: UNBOUNDED diff --git a/mitmproxy-config.yaml b/config-local.yaml similarity index 100% rename from mitmproxy-config.yaml rename to config-local.yaml diff --git a/config-wiiu.yaml b/config-wiiu.yaml new file mode 100644 index 0000000..2bccbc3 --- /dev/null +++ b/config-wiiu.yaml @@ -0,0 +1,9 @@ +listen_port: 8082 +web_port: 8081 + +hardump: ./pretendo-network-dump-wiiu.har + +client_certs: ./client-certificates/WiiU-common.pem +ssl_insecure: true +tls_version_client_min: UNBOUNDED +tls_version_server_min: UNBOUNDED From de65777024d88d60bbbce4bded15f024abe42f0b Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 4 Jan 2024 08:34:40 -0500 Subject: [PATCH 62/74] Set up the Docker publish workflow for multiple configs --- .github/workflows/docker.yml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index d2560ce..7b1baf3 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -7,6 +7,12 @@ on: jobs: build-publish: + strategy: + matrix: + config: + - local # Redirect Pretendo requests to a local server (default) + - wiiu # For Wii U network dumps + - 3ds # For 3DS network dumps runs-on: ubuntu-latest steps: @@ -16,9 +22,14 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 + - name: Set up the ${{ matrix.config }} config + run: | + rm ./.mitmproxy/config.yaml + ln -s ./config-${{ matrix.config }}.yaml ./.mitmproxy/config.yaml + - name: Log into the GitHub container registry if: - ${{ github.event != 'pull_request' && github.ref == 'refs/heads/main' }} + ${{ github.event != 'pull_request' && github.ref == 'refs/heads/master' }} uses: docker/login-action@v3 with: registry: ghcr.io @@ -30,7 +41,11 @@ jobs: uses: docker/metadata-action@v5 with: images: ghcr.io/${{ github.repository }} - flavor: latest=true + flavor: latest=${{ matrix.config == 'local' }} + tags: | + type=ref,event=branch,enable=${{ matrix.config == 'local' }} + type=raw,value=${{ matrix.config }} + type=sha - name: Build and push Docker image id: build-and-push @@ -38,8 +53,7 @@ jobs: with: context: . push: - ${{ github.event != 'pull_request' && github.ref == - 'refs/heads/main' }} + ${{ github.event != 'pull_request' && github.ref == 'refs/heads/master' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha From 4ec0a261100f8546b00e15e5fd942df920904db8 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 4 Jan 2024 08:39:16 -0500 Subject: [PATCH 63/74] Remove the unneeded type=sha --- .github/workflows/docker.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7b1baf3..20592e3 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -45,7 +45,6 @@ jobs: tags: | type=ref,event=branch,enable=${{ matrix.config == 'local' }} type=raw,value=${{ matrix.config }} - type=sha - name: Build and push Docker image id: build-and-push From b3ceb8f8cda9e16e393428930d208863bb8fcbd1 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 4 Jan 2024 08:55:03 -0500 Subject: [PATCH 64/74] Add web_host to network dump configs This is required when running in Docker. --- config-3ds.yaml | 1 + config-wiiu.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/config-3ds.yaml b/config-3ds.yaml index a8e02f1..dfb76d3 100644 --- a/config-3ds.yaml +++ b/config-3ds.yaml @@ -1,5 +1,6 @@ listen_port: 8083 web_port: 8081 +web_host: 0.0.0.0 hardump: ./pretendo-network-dump-3ds.har diff --git a/config-wiiu.yaml b/config-wiiu.yaml index 2bccbc3..0c8ae6f 100644 --- a/config-wiiu.yaml +++ b/config-wiiu.yaml @@ -1,5 +1,6 @@ listen_port: 8082 web_port: 8081 +web_host: 0.0.0.0 hardump: ./pretendo-network-dump-wiiu.har From a8a687a7b3d06659ec59dab4337e3501eb3ac58f Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 4 Jan 2024 09:18:46 -0500 Subject: [PATCH 65/74] Add docs for the network dumps --- README.md | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index fdb0ac5..81d7f13 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,42 @@ This repo contains configurations, scripts, and certificates for using `mitmproxy`/`mitmweb`/`mitmdump` to intercept traffic from Nintendo consoles, -including the Wii U and the 3DS. This fork is designed to work with a local -Pretendo Network server. - -## Usage - -### All setups +including the Wii U and the 3DS. It supports multiple operation modes, including +redirecting requests to a local Pretendo Network server and collecting Wii U and +3DS network dumps. + +## Collecting network dumps + +1. Download and install [Docker](https://docs.docker.com/get-docker/). +2. Download the right patches for your console. + +3. Run the container. Use these commands depending on your console. + - Wii U: `docker run -it --rm -p 8082:8082 -p 127.0.0.1:8081:8081 ghcr.io/pretendonetwork/mitmproxy-nintendo:wiiu mitmdump` + - 3DS: `docker run -it --rm -p 8083:8083 -p 127.0.0.1:8081:8081 ghcr.io/pretendonetwork/mitmproxy-nintendo:3ds mitmdump` +4. Configure your console to connect to the proxy server. + - Wii U: + 1. Open System Settings => Internet => Connect to the Internet => + Connections => (Your current internet connection) => Change Settings. + 2. Go to Proxy Settings => Set => OK => (Set the proxy server to your + server's IP address and the port to 8080) => Confirm => Don't Use + Authentication. + - 3DS: + 1. Open System Settings => Internet Settings => Connection Settings => + (Your current connection) => Change Settings. + 2. Go to Proxy Settings => Yes => Detailed Setup => (Set the proxy server + to your server's IP address and the port to 8080) => OK => Don't Use + Authentication. +5. Check your terminal window to make sure that your console is connecting to the + proxy server. You should see "client connect" and "client disonnect" + messages. +6. Do whatever activity you want to have in the network dump. +7. Press `Ctrl` and `c` at the same time in the terminal window to stop the + proxy and create the dump HAR file. + + +## Local server redirection + +### Steps 1. Choose a method below to run mitmproxy ([Docker](#running-with-docker) or [local install](#running-locally)). From a8ed7db32348d78b2d44801e4c87703de79f28a6 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 4 Jan 2024 13:02:01 -0500 Subject: [PATCH 66/74] Add ARM64 builds --- .github/workflows/docker.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 20592e3..e31d386 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -19,6 +19,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + - name: Set up QEMU for Docker + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -51,6 +54,7 @@ jobs: uses: docker/build-push-action@v5 with: context: . + platforms: linux/amd64,linux/arm64 push: ${{ github.event != 'pull_request' && github.ref == 'refs/heads/master' }} tags: ${{ steps.meta.outputs.tags }} From d9c20972eea22c2ed0ef56baa08c06de269a9ee3 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 4 Jan 2024 18:56:30 -0500 Subject: [PATCH 67/74] Minor config updates --- .gitignore | 3 +++ config-3ds.yaml | 20 ++++++++++---------- config-local.yaml | 2 +- config-wiiu.yaml | 20 ++++++++++---------- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 6d62816..a0b49e2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ # Python cache __pycache__ + +# Network dumps +*.har diff --git a/config-3ds.yaml b/config-3ds.yaml index dfb76d3..cf1d981 100644 --- a/config-3ds.yaml +++ b/config-3ds.yaml @@ -1,10 +1,10 @@ -listen_port: 8083 -web_port: 8081 -web_host: 0.0.0.0 - -hardump: ./pretendo-network-dump-3ds.har - -client_certs: ./client-certificates/CTR-common.pem -ssl_insecure: true -tls_version_client_min: UNBOUNDED -tls_version_server_min: UNBOUNDED +listen_port: 8083 +web_port: 8081 +web_host: 0.0.0.0 + +hardump: ./dumps/3ds-latest.har + +client_certs: ./client-certificates/CTR-common.pem +ssl_insecure: true +tls_version_client_min: UNBOUNDED +tls_version_server_min: UNBOUNDED diff --git a/config-local.yaml b/config-local.yaml index c9fec0c..d61de43 100644 --- a/config-local.yaml +++ b/config-local.yaml @@ -12,7 +12,7 @@ scripts: ["../pretendo_addon.py"] pretendo_redirect: true # Set up redirection to a local server -pretendo_host: nginx +pretendo_host: 127.0.0.1 pretendo_host_port: 80 pretendo_http: true diff --git a/config-wiiu.yaml b/config-wiiu.yaml index 0c8ae6f..d6ba264 100644 --- a/config-wiiu.yaml +++ b/config-wiiu.yaml @@ -1,10 +1,10 @@ -listen_port: 8082 -web_port: 8081 -web_host: 0.0.0.0 - -hardump: ./pretendo-network-dump-wiiu.har - -client_certs: ./client-certificates/WiiU-common.pem -ssl_insecure: true -tls_version_client_min: UNBOUNDED -tls_version_server_min: UNBOUNDED +listen_port: 8082 +web_port: 8081 +web_host: 0.0.0.0 + +hardump: ./dumps/wiiu-latest.har + +client_certs: ./client-certificates/WiiU-common.pem +ssl_insecure: true +tls_version_client_min: UNBOUNDED +tls_version_server_min: UNBOUNDED From 57fe3cb683b02a39f9514c1cd4fd44335967014d Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 4 Jan 2024 19:13:34 -0500 Subject: [PATCH 68/74] Fix the symlink target --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index e31d386..0346e90 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -28,7 +28,7 @@ jobs: - name: Set up the ${{ matrix.config }} config run: | rm ./.mitmproxy/config.yaml - ln -s ./config-${{ matrix.config }}.yaml ./.mitmproxy/config.yaml + ln -s ../config-${{ matrix.config }}.yaml ./.mitmproxy/config.yaml - name: Log into the GitHub container registry if: From 72dec8bd33108ef5dfe0ae7af7f09f9c4925eced Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 4 Jan 2024 19:28:17 -0500 Subject: [PATCH 69/74] Update the network dumping docs --- README.md | 121 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 69 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 81d7f13..80648ef 100644 --- a/README.md +++ b/README.md @@ -8,32 +8,47 @@ redirecting requests to a local Pretendo Network server and collecting Wii U and ## Collecting network dumps -1. Download and install [Docker](https://docs.docker.com/get-docker/). -2. Download the right patches for your console. - -3. Run the container. Use these commands depending on your console. - - Wii U: `docker run -it --rm -p 8082:8082 -p 127.0.0.1:8081:8081 ghcr.io/pretendonetwork/mitmproxy-nintendo:wiiu mitmdump` - - 3DS: `docker run -it --rm -p 8083:8083 -p 127.0.0.1:8081:8081 ghcr.io/pretendonetwork/mitmproxy-nintendo:3ds mitmdump` -4. Configure your console to connect to the proxy server. - - Wii U: - 1. Open System Settings => Internet => Connect to the Internet => - Connections => (Your current internet connection) => Change Settings. - 2. Go to Proxy Settings => Set => OK => (Set the proxy server to your - server's IP address and the port to 8080) => Confirm => Don't Use - Authentication. - - 3DS: - 1. Open System Settings => Internet Settings => Connection Settings => - (Your current connection) => Change Settings. - 2. Go to Proxy Settings => Yes => Detailed Setup => (Set the proxy server - to your server's IP address and the port to 8080) => OK => Don't Use - Authentication. -5. Check your terminal window to make sure that your console is connecting to the - proxy server. You should see "client connect" and "client disonnect" +1. Download and install Docker using the + [official guide](https://docs.docker.com/get-docker/). +2. First, make sure to **disable** Inkay or Nimbus to ensure that you are + connected to the official Nintendo Network servers. Then, download the right + NoSSL patches for your console. + +3. Configure your console to connect to the proxy server. + - Wii U: + 1. Open System Settings => Internet => Connect to the Internet => + Connections => (Your current internet connection) => Change Settings. + 2. Go to Proxy Settings => Set => OK => (Set the proxy server to your + computer's IP address and the port to 8082) => Confirm => Don't Use + Authentication. + - 3DS: + 1. Open System Settings => Internet Settings => Connection Settings => + (Your current connection) => Change Settings. + 2. Go to Proxy Settings => Yes => Detailed Setup => (Set the proxy + server to your computer's IP address and the port to 8083) => OK => + Don't Use Authentication. +4. Copy the command that matches your console and paste it inside a terminal + window to start the proxy server inside a Docker container. + - Wii U: + `docker run -it --rm -p 8082:8082 -v ./dumps:/home/mitmproxy/dumps ghcr.io/pretendonetwork/mitmproxy-nintendo:wiiu mitmdump` + - 3DS: + `docker run -it --rm -p 8083:8083 -v ./dumps:/home/mitmproxy/dumps ghcr.io/pretendonetwork/mitmproxy-nintendo:3ds mitmdump` +5. Check your terminal window to make sure that your console is connecting to + the proxy server. You should see some "client connect" and "client disonnect" messages. 6. Do whatever activity you want to have in the network dump. -7. Press `Ctrl` and `c` at the same time in the terminal window to stop the - proxy and create the dump HAR file. - +7. Press `Control` and `c` in the terminal window to stop the proxy and create + the dump HAR file in the `dumps` folder. +8. Rename the HAR file to something descriptive. +9. Go back to step 4 for your next network dump. +10. Upload your HAR files to the Pretendo Network Discord server to share them + with the developers. + - **Note: Make sure to upload the HAR files directly so they can be + automatically processed to scrub personal information. Don't zip them.** + +When you are finished with collecting network dumps, go back into your console's +Internet settings and disable the proxy server. For security reasons, please +also delete the NoSSL patch you downloaded in step 2. ## Local server redirection @@ -52,13 +67,13 @@ latest image and is already set up with OpenSSL 1.1.1. [official instructions](https://docs.docker.com/get-docker/). 2. Run a new Docker container using the `ghcr.io/matthewl246/mitmproxy-pretendo` image. - - If you're not familiar with Docker, copy the `docker run ...` command from - [this script](./start-docker.sh) to get started. Then, open - in your browser to access the `mitmweb` web - interface for mitmproxy. - - Note that if you delete the `mitmproxy-pretendo-data` volume, the mitmproxy - server certificates will be regenerated and you will need to set up the SSL - patches with your custom certificates again. + - If you're not familiar with Docker, copy the `docker run ...` command from + [this script](./start-docker.sh) to get started. Then, open + in your browser to access the `mitmweb` web + interface for mitmproxy. + - Note that if you delete the `mitmproxy-pretendo-data` volume, the + mitmproxy server certificates will be regenerated and you will need to set + up the SSL patches with your custom certificates again. #### Rebuilding the Docker image @@ -69,7 +84,7 @@ If you want to make modifications to the image, you need to rebuild it locally. 2. Use the `./start-docker.sh` script to build and run the container. This build overwrites the version you downloaded from the container registry. This will take a few minutes the first time, but it will be cached for future builds. - - You need to rebuild the container every time you change something here. + - You need to rebuild the container every time you change something here. If you want to revert your local image to the published version, run `docker pull ghcr.io/matthewl246/mitmproxy-pretendo`. @@ -91,30 +106,30 @@ fail if mitmproxy is using OpenSSL 3.0.0. 3. Create a virtual environment with `python3 -m venv venv`. 4. Activate the virtual environment with `. ./venv/bin/activate`. 5. Install [mitmproxy](https://mitmproxy.org/) with `pip install mitmproxy`. - - Test that mitmproxy is working by running `mitmproxy --version`. - - If the OpenSSL version is above 3.0.0, the console will fail to connect via - HTTPS. Consider using the Docker container instead, or compile a custom - version of OpenSSL and Python cryptography - ([see below](#using-a-custom-version-of-openssl-with-mitmproxy)). + - Test that mitmproxy is working by running `mitmproxy --version`. + - If the OpenSSL version is above 3.0.0, the console will fail to connect + via HTTPS. Consider using the Docker container instead, or compile a + custom version of OpenSSL and Python cryptography + ([see below](#using-a-custom-version-of-openssl-with-mitmproxy)). 6. Run one of the launcher scripts (i.e. `./mitmproxy`) to launch the mitmproxy server. -Running the launcher script will now automatically load the Pretendo addon -script. This will add the custom `pretendo_redirect` and `pretendo_http` options -to mitmproxy. +Running the launcher script will automatically load the Pretendo addon script. +This will add the custom `pretendo_*` options to mitmproxy that allow you to +redirect HTTP requests to your local server. ## Console setup 1. Install Pretendo Network patches on your console using [the official guide](https://pretendo.network/docs/install): - - Download the patches for - [Wii U](https://github.com/PretendoNetwork/Inkay/releases) or - [3DS](https://github.com/PretendoNetwork/nimbus/releases). - - Skip creating a PNID on the official Pretendo server if you will be hosting - your own server. - - If you want to use Juxtaposition, you'll now need to recompile the patches - with your custom certificate - ([see below](#compiling-custom-pretendo-patches)). + - Download the patches for + [Wii U](https://github.com/PretendoNetwork/Inkay/releases) or + [3DS](https://github.com/PretendoNetwork/nimbus/releases). + - Skip creating a PNID on the official Pretendo server if you will be + hosting your own server. + - If you want to use Juxtaposition, you'll now need to recompile the patches + with your custom certificate + ([see below](#compiling-custom-pretendo-patches)). 2. Configure your console to connect to the proxy using its system settings. Set the console's proxy server to your computer's IP address and the port to 8080. @@ -132,10 +147,10 @@ Fortunately, it's pretty easy if you use Docker to compile the patches. 1. Clone the Inkay patcher (`git clone https://github.com/PretendoNetwork/Inkay.git`) 2. Copy your mitmproxy certificate. - - If you're using the Docker container, run - `docker run -it --rm -v mitmproxy-pretendo-data:/mnt busybox cat /mnt/mitmproxy-ca-cert.pem`. - - If you're running mitmproxy locally, run - `cat .mitmproxy/mitmproxy-ca-cert.pem`. + - If you're using the Docker container, run + `docker run -it --rm -v mitmproxy-pretendo-data:/mnt busybox cat /mnt/mitmproxy-ca-cert.pem`. + - If you're running mitmproxy locally, run + `cat .mitmproxy/mitmproxy-ca-cert.pem`. 3. Replace the contents of `./Inkay/data/ca.pem` with your mitmproxy certificate. 4. Run `docker build Inkay -t inkay-build` to build the Inkay build environment. @@ -172,6 +187,8 @@ cryptography in your mitmproxy virtual environment. ### Permanently replacing server certificates +#### **_Notice: This method is deprecated and unsafe. Use a NoSSL patch instead._** + If you want to intercept your console's HTTPS traffic with mitmproxy all the time without using the Pretendo patches, you will need to replace your console's server certificate with the mitmproxy certificate. Note that this is somewhat From 7e66dfead9c7a94cc1ba2f362b6b2f0628ed2fdb Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Thu, 4 Jan 2024 09:19:30 -0500 Subject: [PATCH 70/74] Prepare for merge to upstream --- .github/dependabot.yml | 2 - README.md | 96 +++++++++++++++++++++--------------------- start-docker.sh | 4 +- 3 files changed, 50 insertions(+), 52 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1c4864e..253bcb7 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,5 +4,3 @@ updates: directory: / schedule: interval: daily - assignees: - - MatthewL246 diff --git a/README.md b/README.md index 80648ef..38ab094 100644 --- a/README.md +++ b/README.md @@ -13,26 +13,26 @@ redirecting requests to a local Pretendo Network server and collecting Wii U and 2. First, make sure to **disable** Inkay or Nimbus to ensure that you are connected to the official Nintendo Network servers. Then, download the right NoSSL patches for your console. - + 3. Configure your console to connect to the proxy server. - - Wii U: - 1. Open System Settings => Internet => Connect to the Internet => - Connections => (Your current internet connection) => Change Settings. - 2. Go to Proxy Settings => Set => OK => (Set the proxy server to your - computer's IP address and the port to 8082) => Confirm => Don't Use - Authentication. - - 3DS: - 1. Open System Settings => Internet Settings => Connection Settings => - (Your current connection) => Change Settings. - 2. Go to Proxy Settings => Yes => Detailed Setup => (Set the proxy - server to your computer's IP address and the port to 8083) => OK => - Don't Use Authentication. + - Wii U: + 1. Open System Settings => Internet => Connect to the Internet => + Connections => (Your current internet connection) => Change Settings. + 2. Go to Proxy Settings => Set => OK => (Set the proxy server to your + computer's IP address and the port to 8082) => Confirm => Don't Use + Authentication. + - 3DS: + 1. Open System Settings => Internet Settings => Connection Settings => + (Your current connection) => Change Settings. + 2. Go to Proxy Settings => Yes => Detailed Setup => (Set the proxy server + to your computer's IP address and the port to 8083) => OK => Don't Use + Authentication. 4. Copy the command that matches your console and paste it inside a terminal window to start the proxy server inside a Docker container. - - Wii U: - `docker run -it --rm -p 8082:8082 -v ./dumps:/home/mitmproxy/dumps ghcr.io/pretendonetwork/mitmproxy-nintendo:wiiu mitmdump` - - 3DS: - `docker run -it --rm -p 8083:8083 -v ./dumps:/home/mitmproxy/dumps ghcr.io/pretendonetwork/mitmproxy-nintendo:3ds mitmdump` + - Wii U: + `docker run -it --rm -p 8082:8082 -v ./dumps:/home/mitmproxy/dumps ghcr.io/pretendonetwork/mitmproxy-nintendo:wiiu mitmdump` + - 3DS: + `docker run -it --rm -p 8083:8083 -v ./dumps:/home/mitmproxy/dumps ghcr.io/pretendonetwork/mitmproxy-nintendo:3ds mitmdump` 5. Check your terminal window to make sure that your console is connecting to the proxy server. You should see some "client connect" and "client disonnect" messages. @@ -60,34 +60,34 @@ also delete the NoSSL patch you downloaded in step 2. ### Running with Docker -This is the recommended way to run mitmproxy-pretendo because it always uses the +This is the recommended way to run mitmproxy-nintendo because it always uses the latest image and is already set up with OpenSSL 1.1.1. 1. Install Docker using the [official instructions](https://docs.docker.com/get-docker/). -2. Run a new Docker container using the `ghcr.io/matthewl246/mitmproxy-pretendo` - image. - - If you're not familiar with Docker, copy the `docker run ...` command from - [this script](./start-docker.sh) to get started. Then, open - in your browser to access the `mitmweb` web - interface for mitmproxy. - - Note that if you delete the `mitmproxy-pretendo-data` volume, the - mitmproxy server certificates will be regenerated and you will need to set - up the SSL patches with your custom certificates again. +2. Run a new Docker container using the + `ghcr.io/pretendonetwork/mitmproxy-nintendo` image. + - If you're not familiar with Docker, copy the `docker run ...` command from + [this script](./start-docker.sh) to get started. Then, open + in your browser to access the `mitmweb` web + interface for mitmproxy. + - Note that if you delete the `mitmproxy-pretendo-data` volume, the mitmproxy + server certificates will be regenerated and you will need to set up the SSL + patches with your custom certificates again. #### Rebuilding the Docker image If you want to make modifications to the image, you need to rebuild it locally. 1. Clone this repository to your computer - (`git clone https://github.com/MatthewL246/mitmproxy-pretendo.git`). + (`git clone https://github.com/PretendoNetwork/mitmproxy-nintendo.git`). 2. Use the `./start-docker.sh` script to build and run the container. This build overwrites the version you downloaded from the container registry. This will take a few minutes the first time, but it will be cached for future builds. - - You need to rebuild the container every time you change something here. + - You need to rebuild the container every time you change something here. If you want to revert your local image to the published version, run -`docker pull ghcr.io/matthewl246/mitmproxy-pretendo`. +`docker pull ghcr.io/pretendonetwork/mitmproxy-nintendo`. ### Running locally @@ -102,15 +102,15 @@ fail if mitmproxy is using OpenSSL 3.0.0. 1. Install Python 3 and pip. 2. Clone this repository to your computer - (`git clone https://github.com/MatthewL246/mitmproxy-pretendo.git`). + (`git clone https://github.com/PretendoNetwork/mitmproxy-nintendo.git`). 3. Create a virtual environment with `python3 -m venv venv`. 4. Activate the virtual environment with `. ./venv/bin/activate`. 5. Install [mitmproxy](https://mitmproxy.org/) with `pip install mitmproxy`. - - Test that mitmproxy is working by running `mitmproxy --version`. - - If the OpenSSL version is above 3.0.0, the console will fail to connect - via HTTPS. Consider using the Docker container instead, or compile a - custom version of OpenSSL and Python cryptography - ([see below](#using-a-custom-version-of-openssl-with-mitmproxy)). + - Test that mitmproxy is working by running `mitmproxy --version`. + - If the OpenSSL version is above 3.0.0, the console will fail to connect via + HTTPS. Consider using the Docker container instead, or compile a custom + version of OpenSSL and Python cryptography + ([see below](#using-a-custom-version-of-openssl-with-mitmproxy)). 6. Run one of the launcher scripts (i.e. `./mitmproxy`) to launch the mitmproxy server. @@ -122,14 +122,14 @@ redirect HTTP requests to your local server. 1. Install Pretendo Network patches on your console using [the official guide](https://pretendo.network/docs/install): - - Download the patches for - [Wii U](https://github.com/PretendoNetwork/Inkay/releases) or - [3DS](https://github.com/PretendoNetwork/nimbus/releases). - - Skip creating a PNID on the official Pretendo server if you will be - hosting your own server. - - If you want to use Juxtaposition, you'll now need to recompile the patches - with your custom certificate - ([see below](#compiling-custom-pretendo-patches)). + - Download the patches for + [Wii U](https://github.com/PretendoNetwork/Inkay/releases) or + [3DS](https://github.com/PretendoNetwork/nimbus/releases). + - Skip creating a PNID on the official Pretendo server if you will be hosting + your own server. + - If you want to use Juxtaposition, you'll now need to recompile the patches + with your custom certificate + ([see below](#compiling-custom-pretendo-patches)). 2. Configure your console to connect to the proxy using its system settings. Set the console's proxy server to your computer's IP address and the port to 8080. @@ -147,10 +147,10 @@ Fortunately, it's pretty easy if you use Docker to compile the patches. 1. Clone the Inkay patcher (`git clone https://github.com/PretendoNetwork/Inkay.git`) 2. Copy your mitmproxy certificate. - - If you're using the Docker container, run - `docker run -it --rm -v mitmproxy-pretendo-data:/mnt busybox cat /mnt/mitmproxy-ca-cert.pem`. - - If you're running mitmproxy locally, run - `cat .mitmproxy/mitmproxy-ca-cert.pem`. + - If you're using the Docker container, run + `docker run -it --rm -v mitmproxy-pretendo-data:/mnt busybox cat /mnt/mitmproxy-ca-cert.pem`. + - If you're running mitmproxy locally, run + `cat .mitmproxy/mitmproxy-ca-cert.pem`. 3. Replace the contents of `./Inkay/data/ca.pem` with your mitmproxy certificate. 4. Run `docker build Inkay -t inkay-build` to build the Inkay build environment. diff --git a/start-docker.sh b/start-docker.sh index 49f30c4..4134072 100755 --- a/start-docker.sh +++ b/start-docker.sh @@ -1,4 +1,4 @@ #! /bin/sh -docker build . -t ghcr.io/matthewl246/mitmproxy-pretendo -docker run -it --rm --name mitmproxy-pretendo -v mitmproxy-pretendo-data:/home/mitmproxy/.mitmproxy -p 8080:8080 -p 127.0.0.1:8081:8081 ghcr.io/matthewl246/mitmproxy-pretendo mitmweb --web-host 0.0.0.0 +docker build . -t ghcr.io/pretendonetwork/mitmproxy-nintendo +docker run -it --rm --name mitmproxy-pretendo -v mitmproxy-pretendo-data:/home/mitmproxy/.mitmproxy -p 8080:8080 -p 127.0.0.1:8081:8081 ghcr.io/pretendonetwork/mitmproxy-nintendo mitmweb --web-host 0.0.0.0 From 5d756540c1e67138fceb5ef97bf5ce6f28b11eeb Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Fri, 5 Jan 2024 09:42:11 -0500 Subject: [PATCH 71/74] Add a warning about overwriting dumps --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 38ab094..5c3c9a2 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,10 @@ redirecting requests to a local Pretendo Network server and collecting Wii U and 6. Do whatever activity you want to have in the network dump. 7. Press `Control` and `c` in the terminal window to stop the proxy and create the dump HAR file in the `dumps` folder. -8. Rename the HAR file to something descriptive. +8. Rename the HAR file (`wiiu-latest.har` or `3ds-latest.har`) in the `dumps` + folder to something descriptive. + - **Warning: If you don't rename the dump before restarting the proxy + container, it will be overwritten!** 9. Go back to step 4 for your next network dump. 10. Upload your HAR files to the Pretendo Network Discord server to share them with the developers. From 4d27c67c82651591172a714cda433692d74772a6 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Fri, 5 Jan 2024 10:16:03 -0500 Subject: [PATCH 72/74] Update some wording in the readme --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5c3c9a2..305803a 100644 --- a/README.md +++ b/README.md @@ -37,17 +37,20 @@ redirecting requests to a local Pretendo Network server and collecting Wii U and the proxy server. You should see some "client connect" and "client disonnect" messages. 6. Do whatever activity you want to have in the network dump. -7. Press `Control` and `c` in the terminal window to stop the proxy and create - the dump HAR file in the `dumps` folder. +7. Press `Control` and `c` in the terminal window to stop the proxy. This will + create a network dump HAR file in the `dumps` folder, which you can find in + the current folder that your terminal is running in (if you don't know, run + the `pwd` command). 8. Rename the HAR file (`wiiu-latest.har` or `3ds-latest.har`) in the `dumps` folder to something descriptive. - **Warning: If you don't rename the dump before restarting the proxy container, it will be overwritten!** 9. Go back to step 4 for your next network dump. -10. Upload your HAR files to the Pretendo Network Discord server to share them - with the developers. +10. Upload your HAR files to any public channel in the Pretendo Network + Discord server to share them with the developers. - **Note: Make sure to upload the HAR files directly so they can be - automatically processed to scrub personal information. Don't zip them.** + automatically deleted and reuploaded in a private channel for the + developers. Don't zip the folder.** When you are finished with collecting network dumps, go back into your console's Internet settings and disable the proxy server. For security reasons, please From 994250f7df16b8a40f3ee71229d48abe67a1d100 Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Fri, 5 Jan 2024 12:04:41 -0500 Subject: [PATCH 73/74] Add the NoSSL patches and instructions for them --- README.md | 10 +++++++--- ssl-patches/0004013000002F02.ips | Bin 0 -> 37 bytes ssl-patches/30_nossl.rpx | Bin 0 -> 55348 bytes 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 ssl-patches/0004013000002F02.ips create mode 100644 ssl-patches/30_nossl.rpx diff --git a/README.md b/README.md index 305803a..58daf44 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,11 @@ redirecting requests to a local Pretendo Network server and collecting Wii U and 2. First, make sure to **disable** Inkay or Nimbus to ensure that you are connected to the official Nintendo Network servers. Then, download the right NoSSL patches for your console. - + - Wii U: Download [this patch](./ssl-patches/30_nossl.rpx) and copy it to + your SD card as `sd:/wiiu/environments/aroma/modules/setup/30_nossl.rpx`. + (Replace `aroma` with `tiramisu` if you use Tiramisu.) + - 3DS: Download [this patch](./ssl-patches/0004013000002F02.ips) and copy it + to your microSD card as `sd:/luma/sysmodules/0004013000002F02.ips`. 3. Configure your console to connect to the proxy server. - Wii U: 1. Open System Settings => Internet => Connect to the Internet => @@ -46,8 +50,8 @@ redirecting requests to a local Pretendo Network server and collecting Wii U and - **Warning: If you don't rename the dump before restarting the proxy container, it will be overwritten!** 9. Go back to step 4 for your next network dump. -10. Upload your HAR files to any public channel in the Pretendo Network - Discord server to share them with the developers. +10. Upload your HAR files to any public channel in the Pretendo Network Discord + server to share them with the developers. - **Note: Make sure to upload the HAR files directly so they can be automatically deleted and reuploaded in a private channel for the developers. Don't zip the folder.** diff --git a/ssl-patches/0004013000002F02.ips b/ssl-patches/0004013000002F02.ips new file mode 100644 index 0000000000000000000000000000000000000000..881869ab3a8e66b01d6d4b90a3d6f7a6e957023d GIT binary patch literal 37 scmWG=3~}~g$O&VRcrN?X+)8?agtP&x^WG!|J(dd!G71KUGOqq^0LCl{;{X5v literal 0 HcmV?d00001 diff --git a/ssl-patches/30_nossl.rpx b/ssl-patches/30_nossl.rpx new file mode 100644 index 0000000000000000000000000000000000000000..884c4228d40b39547c9631894556141e2f9f203a GIT binary patch literal 55348 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 Z(2y|0;_ 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%0DOYR*O~RE#COiw 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 C@`YUh literal 0 HcmV?d00001 From 41853f1988d6c03a73869f2e786f4e171b5bf31d Mon Sep 17 00:00:00 2001 From: Matthew Lopez <73856503+MatthewL246@users.noreply.github.com> Date: Fri, 5 Jan 2024 13:20:41 -0500 Subject: [PATCH 74/74] Address review comments --- README.md | 2 +- config-3ds.yaml | 2 -- config-local.yaml | 4 ---- config-wiiu.yaml | 2 -- 4 files changed, 1 insertion(+), 9 deletions(-) diff --git a/README.md b/README.md index 58daf44..22e4cdc 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ redirecting requests to a local Pretendo Network server and collecting Wii U and the proxy server. You should see some "client connect" and "client disonnect" messages. 6. Do whatever activity you want to have in the network dump. -7. Press `Control` and `c` in the terminal window to stop the proxy. This will +7. Press `Control` and `C` in the terminal window to stop the proxy. This will create a network dump HAR file in the `dumps` folder, which you can find in the current folder that your terminal is running in (if you don't know, run the `pwd` command). diff --git a/config-3ds.yaml b/config-3ds.yaml index cf1d981..5e2ff24 100644 --- a/config-3ds.yaml +++ b/config-3ds.yaml @@ -1,6 +1,4 @@ listen_port: 8083 -web_port: 8081 -web_host: 0.0.0.0 hardump: ./dumps/3ds-latest.har diff --git a/config-local.yaml b/config-local.yaml index d61de43..219d99e 100644 --- a/config-local.yaml +++ b/config-local.yaml @@ -22,7 +22,3 @@ ssl_insecure: true # Allow the console to use older TLS versions tls_version_client_min: UNBOUNDED tls_version_server_min: UNBOUNDED - -# A few convenience features -anticache: true -showhost: true diff --git a/config-wiiu.yaml b/config-wiiu.yaml index d6ba264..193ad8a 100644 --- a/config-wiiu.yaml +++ b/config-wiiu.yaml @@ -1,6 +1,4 @@ listen_port: 8082 -web_port: 8081 -web_host: 0.0.0.0 hardump: ./dumps/wiiu-latest.har