tools(re): remove the port-8081 DNAT that breaks FIFA 17's roster TLS

A client-local nat rule redirecting dport 8081 to the plain-HTTP staging
UTAS host captures the roster/squad-update TLS connection, which is
https://winter15.gosredirector.ea.com:8081/fifa17/fut/rosterupdate.xml.
The staging host completes the TCP handshake then closes on the
ClientHello, so the client retries and shows "An error occurred
downloading the FUT squad update."

Proven by capturing on the server while probing from the client: a
connection addressed to :8081 arrives as dport 8299, while an :8443
control in the same capture yields 75 packets and a clean handshake.

The script deletes only nat rules whose destination port is 8299, then
verifies the endpoint presents CN = winter15.gosredirector.ea.com.
This commit is contained in:
funman300
2026-08-24 16:36:56 +00:00
parent 704482be84
commit 96610ccb16
+58
View File
@@ -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