Local network tool that transparently redirects all X/Twitter traffic to xcancel.com, allowing you to browse Twitter content without directly accessing X's servers.
This guide walks through creating a self-signed Certificate Authority (CA) and generating SSL certificates for intercepting HTTPS traffic to twitter.com/x.com.
Looking for something simpler? Check out SSL_SETUP_MKCERT.md for an automated approach using mkcert that handles CA creation and installation automatically. This manual guide is for those who want full control or can’t install mkcert.
To intercept HTTPS traffic without browser warnings, you need:
Creating and installing a self-signed CA means:
If your CA’s private key is compromised, an attacker could generate trusted certificates for any domain on your devices.
# Create a secure directory for your CA
mkdir -p ~/ssl-ca
cd ~/ssl-ca
chmod 700 ~/ssl-ca
# Generate CA private key (keep this VERY secure!)
openssl genrsa -out ca-key.pem 4096
chmod 400 ca-key.pem
Create a config file for your CA (ca.conf):
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
prompt = no
[req_distinguished_name]
C = US
ST = Your State
L = Your City
O = Your Name
CN = Your Name Personal CA
emailAddress = your-email@example.com
[v3_ca]
basicConstraints = critical, CA:TRUE
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
Generate the CA certificate:
openssl req -new -x509 -days 3650 -key ca-key.pem -out ca-cert.pem -config ca.conf
This creates a CA certificate valid for 10 years.
openssl x509 -in ca-cert.pem -text -noout
You should see:
CA:TRUE in Basic ConstraintsCreate a config file (twitter.conf):
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
C = US
ST = Your State
L = Your City
O = Local Intercept
OU = Proxy
CN = twitter.com
[v3_req]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = twitter.com
DNS.2 = www.twitter.com
DNS.3 = x.com
DNS.4 = www.x.com
DNS.5 = t.co
DNS.6 = www.t.co
DNS.7 = *.twitter.com
DNS.8 = *.x.com
Generate private key and CSR:
# Generate server private key
openssl genrsa -out twitter-key.pem 2048
# Generate CSR
openssl req -new -key twitter-key.pem -out twitter.csr -config twitter.conf
Create signing config (signing.conf):
[v3_req]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = twitter.com
DNS.2 = www.twitter.com
DNS.3 = x.com
DNS.4 = www.x.com
DNS.5 = t.co
DNS.6 = www.t.co
DNS.7 = *.twitter.com
DNS.8 = *.x.com
Sign the certificate:
openssl x509 -req -in twitter.csr -CA ca-cert.pem -CAkey ca-key.pem \
-CAcreateserial -out twitter-cert.pem -days 825 -sha256 \
-extfile signing.conf -extensions v3_req
Note: 825 days (about 2 years) is the maximum validity accepted by modern browsers.
nginx needs the full certificate chain:
cat twitter-cert.pem ca-cert.pem > twitter-bundle.pem
# Check certificate details
openssl x509 -in twitter-cert.pem -text -noout
# Verify certificate chain
openssl verify -CAfile ca-cert.pem twitter-cert.pem
Should output: twitter-cert.pem: OK
Copy certificates to your xcancel-forwarder directory:
cd /path/to/xcancel-forwarder
# Copy server certificate and key
cp ~/ssl-ca/twitter-bundle.pem nginx/ssl/
cp ~/ssl-ca/twitter-key.pem nginx/ssl/
# Set secure permissions
chmod 644 nginx/ssl/twitter-bundle.pem
chmod 600 nginx/ssl/twitter-key.pem
Verify nginx configuration references these files correctly (should already be set):
ssl_certificate /etc/nginx/ssl/twitter_bundle.pem;
ssl_certificate_key /etc/nginx/ssl/twitter_key.pem;
You need to install ca-cert.pem as a trusted root CA on every device that will access the redirected sites.
# GUI method
open ca-cert.pem
# Keychain Access will open, double-click certificate, set "Always Trust"
# Command line method
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ca-cert.pem
Verify:
ca-cert.pem to yourself or host it on a web serverca-cert.pem to your deviceca-cert.pemNote: User-installed CAs are not trusted by all apps on Android. Some apps may still show warnings.
# Run PowerShell as Administrator
certutil -addstore -f "ROOT" ca-cert.pem
Or use GUI:
ca-cert.pem → Install Certificate# Copy CA to system certificates
sudo cp ca-cert.pem /usr/local/share/ca-certificates/twitter-redirect-ca.crt
# Update CA store
sudo update-ca-certificates
sudo trust anchor --store ca-cert.pem
Firefox uses its own certificate store:
ca-cert.pemChrome and Edge use system certificates, so installing via OS methods (above) is sufficient.
nslookup twitter.com
# Should return your nginx server IP
# Should show your certificate
openssl s_client -connect twitter.com:443 -servername twitter.com < /dev/null
# Look for:
# - Issuer: Your CA name
# - Subject: CN=twitter.com
# - Verify return code: 0 (ok)
https://twitter.comIf you see warnings:
Your server certificate expires in 825 days. To renew:
cd ~/ssl-ca
# Generate new CSR with same key (or generate new key)
openssl req -new -key twitter-key.pem -out twitter-new.csr -config twitter.conf
# Sign with your CA
openssl x509 -req -in twitter-new.csr -CA ca-cert.pem -CAkey ca-key.pem \
-CAcreateserial -out twitter-new-cert.pem -days 825 -sha256 \
-extfile signing.conf -extensions v3_req
# Create new bundle
cat twitter-new-cert.pem ca-cert.pem > twitter-new-bundle.pem
# Copy to nginx
cp twitter-new-bundle.pem /path/to/xcancel-forwarder/nginx/ssl/twitter-bundle.pem
# Reload nginx
docker compose restart nginx
No need to reinstall CA on devices unless you regenerated the CA certificate.
openssl verify -CAfile ca-cert.pem twitter-cert.pemEach device needs the CA installed independently. Don’t forget:
Verify Subject Alternative Names (SANs) include all domains:
openssl x509 -in twitter-bundle.pem -text -noout | grep -A 10 "Subject Alternative Name"
Should list: twitter.com, x.com, t.co, and their variants.
chmod 400 ca-key.pem
# Store backup on encrypted USB drive, not cloud storage
If certificate management is too complex, you can skip SSL:
nginx/conf.d/xcancel-redirect.confssl_protocolslisten 443 sslhttp2 onlisten 443 quicssl_certificate and ssl_certificate_keyssl_session_cache and ssl_session_timeoutadd_header Alt-Svc and add_header X-Protocolserver {
listen 80;
server_name twitter.com www.twitter.com x.com www.x.com t.co www.t.co _;
location / {
return 301 https://xcancel.com$request_uri;
}
}
This will work for HTTP-only traffic. HTTPS links will show browser warnings.