diff --git a/fifa17-recon/tools/live/fix-roster-dnat.sh b/fifa17-recon/tools/live/fix-roster-dnat.sh new file mode 100755 index 0000000..9b80cd5 --- /dev/null +++ b/fifa17-recon/tools/live/fix-roster-dnat.sh @@ -0,0 +1,58 @@ +#!/bin/sh +# Remove the port-8081 DNAT rule that hijacks FIFA 17's roster/squad-update TLS. +# +# Why: the FUT squad update is https://winter15.gosredirector.ea.com:8081/fifa17/fut/rosterupdate.xml +# (TLS on port 8081). A DNAT rule rewriting dport 8081 -> 8299 sends that TLS +# handshake to the plain-HTTP staging UTAS host, which closes the connection. +# Proven: a probe to 10.10.0.120:8081 from this box arrives at the server as +# dport 8299. Result: "An error occurred downloading the FUT squad update." +# +# The rule also never redirected UTAS, which lives on :8443, not :8081. +# +# Read-only until it deletes; deletes only nat rules whose target port is 8299. +set -u + +echo "== nat OUTPUT rules mentioning 8081 or 8299 ==" +iptables -t nat -S OUTPUT 2>/dev/null | grep -E '8081|8299' || echo " (none)" + +echo +echo "== deleting DNAT rules that redirect to port 8299 ==" +removed=0 +# Delete by spec, repeatedly, until no matching rule remains. +while :; do + rule=$(iptables -t nat -S OUTPUT 2>/dev/null | grep -m1 -E '\-\-dport 8081 .*8299|to-destination [0-9.]+:8299') + [ -z "$rule" ] && break + spec=$(printf '%s' "$rule" | sed 's/^-A /-D /') + # shellcheck disable=SC2086 + if iptables -t nat $spec 2>/dev/null; then + echo " removed: $rule" + removed=$((removed + 1)) + else + echo " FAILED to remove: $rule" >&2 + break + fi +done +[ "$removed" -eq 0 ] && echo " (no matching rule found)" + +echo +echo "== remaining nat OUTPUT rules mentioning 8081 or 8299 ==" +iptables -t nat -S OUTPUT 2>/dev/null | grep -E '8081|8299' || echo " (none)" + +echo +echo "== verifying the roster endpoint now presents the correct certificate ==" +python3 - <<'PY' +import socket, ssl +host, port, sni = "10.10.0.120", 8081, "winter15.gosredirector.ea.com" +try: + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + ctx.check_hostname = False + ctx.verify_mode = ssl.CERT_NONE + with socket.create_connection((host, port), 8) as s: + with ctx.wrap_socket(s, server_hostname=sni) as t: + der = t.getpeercert(True) + cn = dict(x[0] for x in t.getpeercert().get("subject", ())) + print(f" PASS {host}:{port} sni={sni} {t.version()} der={len(der)}B subject={cn}") +except Exception as e: + print(f" FAIL {host}:{port} sni={sni} -> {type(e).__name__}: {e}") + print(" The roster path is still broken; do not relaunch yet.") +PY