xcancel-forwarder

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.


Project maintained by ryantenney Hosted on GitHub Pages — Theme by mattgraham

Real-World Setup Examples

Complete end-to-end walkthroughs for common xcancel-forwarder configurations.

Each example includes the full setup process, verification steps, and typical issues you might encounter.

Example Index


Example 1: Pi-hole + nginx + macOS/iOS

Scenario: You have Pi-hole running on a Raspberry Pi. You want network-wide redirect that works on your Mac and iPhone.

Your Network:

Step 1: Set Up nginx

# On your laptop
cd ~/
git clone https://github.com/ryantenney/xcancel-forwarder.git
cd xcancel-forwarder

# Create environment file
cp .env.example .env
vim .env

Edit .env:

NGINX_IP=192.168.1.100
LAN_INTERFACE=en0  # Your Mac's interface
LAN_SUBNET=192.168.1.0/24
LAN_GATEWAY=192.168.1.1

Step 2: Enable macvlan

Edit docker-compose.yaml:

Step 3: Set Up SSL (mkcert)

# Install mkcert
brew install mkcert

# Create and install CA
mkcert -install

# Generate certificates
mkcert twitter.com x.com "*.twitter.com" "*.x.com" t.co "*.t.co"

# Move to nginx directory
mv twitter.com+5.pem nginx/ssl/server.crt
mv twitter.com+5-key.pem nginx/ssl/server.key

Step 4: Start nginx

docker compose up -d

# Check status
docker compose ps
# Should show nginx Up/healthy

# Test from another device (not Mac - macvlan limitation)
# From iPhone:
curl http://192.168.1.100
# Should return 301 to xcancel.com

Step 5: Configure Pi-hole

  1. Open Pi-hole web interface: http://192.168.1.2/admin
  2. Login with your password
  3. Go to Local DNSDNS Records
  4. Add these A records:
    • twitter.com192.168.1.100
    • x.com192.168.1.100
    • t.co192.168.1.100
  5. Add CNAME records:
    • *.twitter.comtwitter.com
    • *.x.comx.com
  6. Click Add for each

Step 6: Verify DNS

# Test from Mac
nslookup twitter.com
# Should return 192.168.1.100

# Test other domains
nslookup google.com
# Should return real IP (Pi-hole forwarding)

Step 7: Install CA on macOS

# mkcert already installed it
# Verify:
security find-certificate -c "mkcert" -a
# Should show your CA

Step 8: Test on macOS

  1. Open Safari
  2. Visit https://twitter.com
  3. Should redirect to xcancel.com
  4. No security warnings

Step 9: Install CA on iPhone

  1. On Mac, find CA file:
mkcert -CAROOT
# Shows location, usually: /Users/yourname/Library/Application Support/mkcert
  1. Email the rootCA.pem file to yourself
  2. On iPhone, open email and tap attachment
  3. Follow prompts to install profile
  4. Go to SettingsGeneralAboutCertificate Trust Settings
  5. Enable trust for your CA

Step 10: Test on iPhone

  1. Open Safari
  2. Visit https://twitter.com
  3. Should redirect to xcancel.com
  4. No security warnings

Common Issues

Mac can’t test redirect:

iPhone shows certificate warning:

iPhone not redirecting:


Example 2: dnsmasq + Caddy + Home Network

Scenario: No existing DNS server. You want simplest setup with Caddy for entire home network.

Your Network:

Step 1: Set Up Project

git clone https://github.com/ryantenney/xcancel-forwarder.git
cd xcancel-forwarder

cp .env.example .env
vim .env

Edit .env:

LAN_INTERFACE=eth0
LAN_SUBNET=192.168.1.0/24
LAN_GATEWAY=192.168.1.1
NGINX_IP=192.168.1.100
DNSMASQ_IP=192.168.1.101

Step 2: Configure dnsmasq

Edit dnsmasq/dnsmasq.conf:

# Update nginx IP
address=/twitter.com/192.168.1.100
address=/x.com/192.168.1.100
address=/t.co/192.168.1.100

# Upstream DNS (Cloudflare)
server=1.1.1.1
server=1.0.0.1

Step 3: Enable macvlan and dnsmasq

Edit docker-compose.caddy.yaml:

Step 4: Set Up SSL (mkcert)

# Install mkcert (Linux example)
sudo apt install mkcert

# Create and install CA
mkcert -install

# Generate certificates
mkcert twitter.com x.com "*.twitter.com" "*.x.com" t.co "*.t.co"

# Move to Caddy directory
mv twitter.com+5.pem caddy/ssl/server.crt
mv twitter.com+5-key.pem caddy/ssl/server.key

Step 5: Start Services

docker compose -f docker-compose.caddy.yaml up -d

# Check both containers
docker compose ps
# Should show caddy and dnsmasq both Up

Step 6: Test from Another Device

# From another computer/phone on network
nslookup twitter.com 192.168.1.101
# Should return 192.168.1.100

curl -I http://192.168.1.100
# Should return 301 to xcancel.com

Step 7: Configure Router DHCP

  1. Access router admin: http://192.168.1.1
  2. Find DHCP settings
  3. Set Primary DNS: 192.168.1.101 (your dnsmasq)
  4. Set Secondary DNS: 1.1.1.1 (fallback)
  5. Save and reboot router

Step 8: Reconnect Devices

All devices need to get new DHCP lease:

Step 9: Install CA on All Devices

Windows:

  1. Copy rootCA.pem from Docker host
  2. Double-click certificate
  3. Install → Local Machine → Place in Trusted Root Certification Authorities

Linux:

sudo cp rootCA.pem /usr/local/share/ca-certificates/xcancel-ca.crt
sudo update-ca-certificates

Android:

  1. Copy rootCA.pem to phone
  2. Settings → Security → Install from storage
  3. Select file

iOS: See Example 1 step 9

Step 10: Network-Wide Testing

Test from multiple devices:

# Each device
nslookup twitter.com
# Should return 192.168.1.100

# Browser test
# Visit https://twitter.com
# Should redirect without warnings

Common Issues

Some devices still using old DNS:

DNS not working from Docker host:

dnsmasq port 53 conflict:


Example 3: Router DNS + nginx + Android

Scenario: You can access your router’s DNS settings. Simple setup for Android phone.

Your Network:

Step 1: Simple Docker Setup

git clone https://github.com/ryantenney/xcancel-forwarder.git
cd xcancel-forwarder

# Use default .env (bridge mode)
# No changes needed for bridge networking

Step 2: Skip SSL (HTTP Only)

# Edit nginx/conf.d/xcancel-redirect.conf
# Comment out SSL-related lines:
# - Lines 3, 5, 9, 13-18, 20-21

# Or just remove the HTTPS server block

Step 3: Start nginx

docker compose up -d

# Test
curl -I http://localhost
# Should return 301 to xcancel.com

Step 4: Configure Router DNS

  1. Access router: http://192.168.0.1
  2. Find DNS Settings or Static DNS
  3. Add entries:
    • twitter.com192.168.0.5
    • x.com192.168.0.5
    • t.co192.168.0.5

Note: Not all routers support this. If yours doesn’t, use dnsmasq instead.

Step 5: Configure Android DNS

Since router DNS may not support wildcards:

  1. SettingsNetwork & InternetWi-Fi
  2. Tap your network name
  3. AdvancedIP SettingsStatic
  4. Set DNS 1: Your router (for everything else): 192.168.0.1
  5. Save

Alternative: Leave Wi-Fi on DHCP and edit /etc/hosts (requires root).

Step 6: Clear Android DNS Cache

  1. Enable Airplane Mode
  2. Wait 5 seconds
  3. Disable Airplane Mode

Step 7: Test on Android

  1. Open Chrome
  2. Visit http://twitter.com (note: HTTP, not HTTPS)
  3. Should redirect to xcancel.com
  4. HTTPS will show warning (expected - no SSL)

Limitations

HTTP only:

Manual DNS on Android:

Upgrade Path

To add HTTPS:

  1. Set up mkcert (see Example 1)
  2. Uncomment SSL config in nginx
  3. Install CA on Android
  4. Restart nginx

Example 4: Hosts File Only (No Docker DNS)

Scenario: Single laptop, don’t want to run DNS server, simplest possible setup.

Your Setup:

Step 1: Minimal Docker Setup

git clone https://github.com/ryantenney/xcancel-forwarder.git
cd xcancel-forwarder

# Use all defaults - no .env changes needed

Step 2: Skip SSL

# Edit nginx/conf.d/xcancel-redirect.conf
# Comment out HTTPS server block (lines 9-23)
# Keep only HTTP server block

Step 3: Start nginx

docker compose up -d

# Test
curl -I http://localhost
# Should return 301

Step 4: Edit Hosts File

macOS/Linux:

sudo vim /etc/hosts

# Add these lines:
127.0.0.1 twitter.com www.twitter.com
127.0.0.1 x.com www.x.com
127.0.0.1 t.co

Windows:

# Run as Administrator
notepad C:\Windows\System32\drivers\etc\hosts

# Add these lines:
127.0.0.1 twitter.com www.twitter.com
127.0.0.1 x.com www.x.com
127.0.0.1 t.co

Step 5: Clear DNS Cache

macOS:

sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

Windows:

ipconfig /flushdns

Linux:

sudo systemd-resolve --flush-caches

Step 6: Test

# Test DNS
nslookup twitter.com
# Should return 127.0.0.1

# Test redirect
curl -I http://twitter.com
# Should return 301 to xcancel.com

# Browser
# Visit http://twitter.com
# Should redirect to xcancel.com

Limitations

Wildcard subdomains don’t work:

HTTPS shows warnings:

Single device only:

When to Use

Perfect for:

Not suitable for:


Example 5: Existing nginx Reverse Proxy

Scenario: You already run nginx as reverse proxy (or nginx-proxy-manager). You want to add Twitter redirect without disrupting existing setup.

Your Setup:

Option A: Add Rules to Existing nginx

Don’t run xcancel-forwarder containers. Just add redirect rules.

Step 1: Create Redirect Config

# Add to your existing nginx config
sudo vim /etc/nginx/sites-available/twitter-redirect

# Add this:
server {
    listen 80;
    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;
    }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name twitter.com www.twitter.com x.com www.x.com t.co www.t.co;

    # Use your existing SSL certificates or create new ones
    ssl_certificate /etc/letsencrypt/live/twitter.local/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/twitter.local/privkey.pem;

    location / {
        return 301 https://xcancel.com$request_uri;
    }
}

Step 2: Create SSL Certificate

Since Let’s Encrypt won’t issue certificates for twitter.com (you don’t own it), use self-signed:

# Create certificate
sudo mkcert -install
sudo mkcert twitter.com x.com "*.twitter.com" "*.x.com" t.co "*.t.co"

# Or use your existing CA

Step 3: Enable and Test

# Enable site
sudo ln -s /etc/nginx/sites-available/twitter-redirect /etc/nginx/sites-enabled/

# Test config
sudo nginx -t

# Reload
sudo systemctl reload nginx

# Test
curl -I http://your-server-ip
# Set Host header to test:
curl -I -H "Host: twitter.com" http://your-server-ip
# Should return 301

Step 4: Configure DNS

Use Pi-hole, dnsmasq, or router DNS to point domains to your nginx server IP.

Option B: Run on Different Ports

Run xcancel-forwarder on ports 8080/8443, proxy from main nginx.

Step 1: Change Ports

# docker-compose.yaml (bridge mode)
services:
  nginx:
    ports:
      - "8080:80"
      - "8443:443"

Step 2: Start xcancel-forwarder

docker compose up -d

Step 3: Proxy from Main nginx

# In your main nginx config
server {
    listen 80;
    server_name twitter.com x.com t.co;

    location / {
        proxy_pass http://localhost:8080;
    }
}

server {
    listen 443 ssl;
    server_name twitter.com x.com t.co;

    # Your SSL config...

    location / {
        proxy_pass https://localhost:8443;
    }
}

Step 4: Test

curl -I -H "Host: twitter.com" http://localhost
# Should return 301 from proxied xcancel-forwarder

When to Use Each Option

Option A (add rules):

Option B (proxy to containers):


Comparison of Examples

Example DNS Method Web Server SSL Complexity Best For
#1 Pi-hole nginx mkcert Medium Existing Pi-hole users
#2 dnsmasq Caddy mkcert Medium Whole network, no Pi-hole
#3 Router nginx None Low Router with static DNS
#4 Hosts file nginx None Low Single device testing
#5 Any Existing Your choice Medium Existing reverse proxy

Contributing Examples

Have a different setup? Submit a PR with your example!

Include: