How I Turned My VPS Datacenter IP Into a Residential IP Using an Old Phone
I locked myself out of my own server doing this. Still worth it.
I’ve been running a personal AI assistant on a cloud VPS. It handles conversations, automates tasks, and connects with external services on my behalf. Everything worked, except the outbound IP was a datacenter IP. I wanted it to appear as a residential IP instead, so my assistant interacts with the outside world the same way a normal user would.
This post is the full breakdown: the problem, the solution, every step I took, the mistakes I made, and the trade-offs I’ve discovered since.
Table of Contents
- The Problem
- Goals
- The Idea
- Architecture
- Tools & Why I Chose Them
- Step-by-Step Setup
- How I Locked Myself Out
- Monitoring & Maintenance
- Pros & Cons
- Disclaimer
The Problem
Cloud providers like GCP, AWS, and Azure use IP ranges that are publicly documented. Anyone, including the services your VPS talks to, can look up an IP and immediately tell it’s coming from a datacenter, not a real person’s home network.
This matters because many services treat datacenter IPs differently from residential IPs. Some apply stricter rate limits, some flag automated behavior more aggressively, and some simply expect traffic from “real” users to come from home or mobile networks. If your VPS is making outbound requests that should look like they’re coming from a regular user, a datacenter IP gives it away immediately.
The IP itself isn’t spoofed or masked in any shady way. It’s simply that a 34.x.x.x GCP address tells the world “this is a server in a data center,” and sometimes that’s not what you want.
Goals
| Goal | Detail |
|---|---|
| Residential IP | VPS outbound traffic should show a residential or mobile carrier IP |
| Zero cost | No monthly subscriptions, no new hardware purchases |
| No code changes | The application running on the VPS should not need any modification |
| Stable connection | Should run 24/7 with minimal babysitting |
| Use existing hardware | Only use what I already have: a GCP VPS and a cheap Android phone |
The Idea
If I need a residential IP, I need a residential device. Something that’s actually sitting on a home network, getting an IP from a regular ISP.
Then I remembered an old Android phone collecting dust at home. I charged it up, connected it to my home WiFi, and just like that, it had a residential IP from my ISP.
Now the question became: how do I make this phone a gateway for my VPS?
The answer: a mesh VPN with an exit node.
The concept is simple. Connect your devices into a private encrypted network, and let one device act as the internet gateway for the others. The VPS sends all its traffic through the tunnel to the phone, and the phone forwards it out to the internet. The outside world only sees the phone’s IP.
Architecture
With Tailscale Exit Node (What I Built)
Tailscale Tunnel
(encrypted, WireGuard)
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ │ │ │ │ │
│ Cloud VPS │ ───────► │ Android Phone│ ───────► │ Internet │
│ │ │ (Exit Node) │ │ │
│ AI Assistant│ │ │ │ Sees phone's│
│ runs here │ │ Home WiFi / │ │ residential │
│ │ │ Mobile Data │ │ IP address │
│ IP: hidden │ │ │ │ │
│ (datacenter)│ │ IP: visible │ │ │
│ │ │ (residential)│ │ │
└──────────────┘ └──────────────┘ └──────────────┘
34.x.x.x 182.x.x.x
(never seen) (seen publicly) Traffic flow:
- The app on GCP makes an outbound request
- The traffic enters the Tailscale tunnel (encrypted via WireGuard)
- The traffic exits through the Android phone’s network interface
- The destination sees the phone’s residential IP (e.g.,
182.253.x.x) - Response traffic flows back through the same path in reverse
With a Commercial VPN (The Alternative I Didn’t Choose)
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ │ │ │ │ │
│ Cloud VPS │ ───────► │ VPN Server │ ───────► │ Internet │
│ │ │ │ │ │
│ AI Assistant│ │ VPN company │ │ Sees VPN's │
│ runs here │ │ datacenter │ │ datacenter │
│ │ │ │ │ IP address │
└──────────────┘ └──────────────┘ └──────────────┘
34.x.x.x 104.x.x.x
(never seen) (still datacenter) The Difference
Tailscale exit node: VPS ──► your phone ──► internet = residential IP ✓
Commercial VPN: VPS ──► VPN server ──► internet = datacenter IP ✗ Most commercial VPNs route traffic through their own datacenters. You’re swapping one datacenter IP for another. Some providers do offer residential IPs, but those cost money, typically $1-50+/month depending on the provider.
With a Tailscale exit node, traffic exits through your device, on your network, using your IP. That’s the key difference.
Tools & Why I Chose Them
Tailscale
Tailscale is a mesh VPN built on top of WireGuard. It creates a private network (called a tailnet) between your devices. Each device gets a stable 100.x.x.x Tailscale IP address and can communicate with other devices in the tailnet directly, even behind NATs and firewalls.
Why Tailscale:
- Free tier. Up to 3 users, 100 devices. More than enough for this.
- No server to maintain. Unlike traditional VPNs, Tailscale is peer-to-peer. There’s no central VPN server you need to set up or pay for.
- NAT traversal built-in. Your phone doesn’t need a static IP or port forwarding. Tailscale handles firewall/NAT punching automatically.
- Exit node is a first-party feature. It’s not a hack or workaround. Tailscale explicitly supports using a device as an exit node.
- Easy setup. One install command on the VPS, one app install on the phone.
WireGuard
WireGuard is the underlying VPN protocol that Tailscale uses. It’s a modern, fast, and lightweight protocol built into the Linux kernel. You don’t interact with WireGuard directly. Tailscale wraps it with identity management, key rotation, NAT traversal, and a nice admin console.
The important thing to know: WireGuard is why the tunnel is fast and encrypted. Tailscale is why it’s easy to set up.
Exit Node
An exit node in Tailscale is a device that acts as a gateway for other devices’ internet traffic. When a device uses an exit node, all its outbound internet traffic is routed through that exit node instead of going directly to the internet.
In this setup:
- The Android phone is the exit node (traffic exits through it)
- The GCP VPS is the client (its traffic is routed through the phone)
DERP Relay
When two Tailscale devices can’t establish a direct peer-to-peer connection (due to restrictive NATs or firewalls), Tailscale falls back to DERP (Designated Encrypted Relay for Packets) servers. These are relay servers run by Tailscale that forward encrypted WireGuard packets between devices. The relay cannot see the traffic content.
- Direct connection = faster, lower latency (preferred)
- DERP relay = slower but always works as a fallback
You can check which mode you’re using with tailscale status.
Why Not the Alternatives?
I considered several other approaches before settling on Tailscale:
| Approach | Why I Didn’t Choose It |
|---|---|
| Raw WireGuard tunnel | More control, but significantly more manual setup. Need to handle dynamic IPs, port forwarding, key management. Tailscale does all of this automatically. |
| ZeroTier | Similar concept to Tailscale, but exit node routing is less straightforward and less documented. |
| SOCKS5 proxy on phone (via Termux) | Lightweight, but more moving parts. Need to keep Termux alive, manage the proxy process, handle reconnects. |
| Reverse SSH tunnel | No extra apps needed, but SSH tunnels drop frequently. Need autossh or a keepalive mechanism. Least reliable option. |
| Commercial VPN | Swaps one datacenter IP for another (most VPN providers use datacenter IPs). Residential VPN IPs exist but cost money. |
| Residential proxy service | Reliable, but $1-50+/month. Defeats the zero-cost goal. |
| Cloudflare WARP | Free, but Cloudflare IPs are still not residential. May not solve the problem. |
Tailscale won because it’s free, easy, reliable, and the exit node feature does exactly what I need without any hacks.
Step-by-Step Setup
My Environment
| Resource | Details |
|---|---|
| VPS | GCP e2-medium, Ubuntu 24.04 LTS |
| VPS zone | us-central1-f |
| Phone | Xiaomi Redmi Note 9 (Android 10, 3GB RAM) |
| Phone network | Home WiFi (residential ISP) |
| Tailscale version | 1.94.2 |
Prerequisites
Before starting, make sure you have:
- A Linux VPS (GCP, AWS, or any provider)
- An Android phone (Android 10+) connected to WiFi or mobile data
- The phone plugged into power (it needs to stay on 24/7)
- A Tailscale account, free at login.tailscale.com
- Tailscale app installed on the phone, logged into the same account
- “Run exit node” enabled in the phone’s Tailscale app settings
- The phone approved as an exit node in the Tailscale admin console
Phase 1: Fix DNS First
Do this BEFORE anything else. Android exit nodes have a well-documented DNS bug (GitHub Issue #6119) where connected devices lose internet because DNS resolution fails. If you skip this step and enable the exit node later, you will lose all connectivity on the VPS, including SSH. I learned this the hard way.
- Go to https://login.tailscale.com/admin/dns
- Under “Nameservers”, click “Add nameserver”
- Add Cloudflare Public DNS (
1.1.1.1and the other 3 Cloudflare servers) - Enable “Override local DNS”. This is the critical fix.
- Click Save
This forces all devices in your tailnet to use the specified DNS servers, bypassing the broken DNS path on Android exit nodes.
Warning: Do NOT use
127.0.0.1or local IPs as the nameserver. This will crash the Android VPN service. Use public DNS only.
Phase 2: Install Tailscale on the VPS
curl -fsSL https://tailscale.com/install.sh | sh This installs Tailscale and auto-enables the tailscaled service. In my case, it installed version 1.94.2 via APT.
Phase 3: Authenticate the VPS
sudo tailscale login --timeout=10s This prints an auth URL. Open it in your browser and authorize the machine.
Lesson learned: I used
tailscale login --timeout=10sinstead oftailscale up. The reason is thattailscale upblocks indefinitely waiting for authentication, which causes the SSH session to hang if you’re running it overgcloud compute ssh.tailscale loginwith a timeout prints the URL and exits cleanly.
After authenticating, verify:
tailscale ip -4 # Should show a 100.x.x.x IP
tailscale status # Should show your VPS and phone listed Phase 4: Build the Safety Net
This phase exists because of what happened the first time. I enabled the exit node without any backup access method and got permanently locked out of my VPS. The VM had to be deleted. Full story in How I Locked Myself Out.
The safety net gives you alternative ways to access the VPS when the exit node breaks your normal SSH connection.
4a. Enable Tailscale SSH
sudo tailscale set --ssh This lets you SSH into the VPS through the Tailscale network itself. Even if the exit node breaks regular internet connectivity, Tailscale SSH still works because it goes through the Tailscale tunnel directly. It doesn’t depend on the exit node path.
4b. Test Tailscale SSH from Your Laptop
First, install Tailscale on your laptop and log into the same account. Then:
ssh root@<VPS_TAILSCALE_IP> The first connection may require a browser auth check via Tailscale. After that, SSH works directly through the tunnel.
This is your primary access method from now on. After enabling the exit node, regular
gcloud compute ssh(or any SSH over the public internet) will stop working. Tailscale SSH is the way in.
4c. Set a Linux Password for Serial Console
GCP’s serial console requires a username/password (SSH keys don’t work there). Set one now while you still have access:
sudo passwd <your-username> Remember these credentials. If everything else fails, the serial console is your last resort.
4d. Enable Serial Console on the VM
gcloud compute instances add-metadata <VM_NAME>
--zone=<ZONE> --project=<PROJECT>
--metadata=serial-port-enable=true The serial console is accessible from the GCP Console UI: VM instance page, then “Connect to serial port.” It works even when all network access is broken.
Phase 5: Fix Reverse-Path Filtering
This was not in any guide I found. When I first tried to set the exit node, Tailscale gave me this error:
The following issues on your machine will likely make usage of exit nodes impossible:
- interface "ens4" has strict reverse-path filtering enabled
- interface "tailscale0" has strict reverse-path filtering enabled
Please set rp_filter=2 instead of rp_filter=1 GCP Ubuntu 24.04 has strict reverse-path filtering (rp_filter=1) by default. This blocks exit node traffic because response packets arriving via the Tailscale tunnel get dropped. The kernel sees them arriving on an unexpected interface.
Fix: apply immediately and persist across reboots.
# Apply immediately
sudo sysctl -w net.ipv4.conf.all.rp_filter=2
sudo sysctl -w net.ipv4.conf.ens4.rp_filter=2
sudo sysctl -w net.ipv4.conf.tailscale0.rp_filter=2
# Persist across reboots
cat <<EOF | sudo tee /etc/sysctl.d/99-tailscale.conf
net.ipv4.conf.all.rp_filter=2
net.ipv4.conf.ens4.rp_filter=2
net.ipv4.conf.tailscale0.rp_filter=2
EOF Note: Replace
ens4with your actual network interface name if different. On GCP instances it’s typicallyens4. Check withip link.
Phase 6: Connect to the Phone Exit Node
Pre-Flight Checklist
Before running the command, confirm ALL of these:
- DNS is configured in admin console with “Override local DNS” enabled (Phase 1)
- Tailscale SSH is enabled and tested (Phase 4a, 4b)
- Linux password is set for serial console (Phase 4c)
- Serial port access is enabled on the VM (Phase 4d)
- rp_filter is set to 2 (Phase 5)
- Phone is on, Tailscale app is active, “Run exit node” is enabled, phone is plugged in and on WiFi
- Phone is approved as exit node in the admin console
If any of these are not done, do not proceed. You risk getting locked out.
Set the exit node
sudo tailscale set --exit-node=<PHONE_HOSTNAME> --exit-node-allow-lan-access=true Replace <PHONE_HOSTNAME> with your phone’s Tailscale hostname (visible in tailscale status).
Important: After this command,
gcloud compute sshstops working. Response packets from the VPS get routed through the phone instead of back to your laptop, so the SSH connection times out. This is expected. Use Tailscale SSH from now on.
Phase 7: Verify Everything Works
All verification from this point on is done via Tailscale SSH:
ssh root@<VPS_TAILSCALE_IP> Then run:
# Check your public IP (should show the phone's IP, NOT a GCP IP)
curl -s ifconfig.me
# Check Tailscale connection status
tailscale status
# Look for the phone's entry (should say "direct" not "relay")
tailscale status | grep <PHONE_HOSTNAME> My results:
| Check | Result |
|---|---|
| Public IP | 182.253.124.138 (phone’s residential IP, not GCP’s 34.x.x.x) |
| DNS | Working (curl resolved hostnames correctly) |
| Connection type | Direct (not relayed via DERP) |
| Exit node status | Active on phone |
Done. The VPS now routes all outbound traffic through my phone’s residential IP.
How I Locked Myself Out
This deserves its own section because it’s the most important lesson from the entire project.
What Happened
The first time I set up Tailscale, I did everything in the “obvious” order:
- Install Tailscale on VPS ✓
- Set phone as exit node ✓
- …that’s it. No safety nets. No backup access.
The moment I ran sudo tailscale set --exit-node=<phone>, something went wrong with the tunnel. My SSH session froze. I waited. Timeout.
I tried gcloud compute ssh. Timeout. The GCP Console’s browser SSH. Timeout. IAP tunneling. Timeout.
Every access method failed because they all rely on the VPS sending response packets back over the internet, and all internet traffic was now routing through a broken exit node tunnel.
Why Nothing Worked
| Method | Why It Failed |
|---|---|
gcloud compute ssh | Response packets routed through broken exit node |
| GCP Console SSH | Same reason, response traffic goes through broken exit node |
| IAP tunneling | Same reason, response traffic goes through broken exit node |
| GCP startup script | Can’t fetch script from metadata server (169.254.169.254), traffic routed through broken exit node |
| Removing VPS from Tailscale admin console | Local routing rules (table 52) persist even after tailscaled enters “logged out” state |
| Turning off Tailscale on the phone | VPS keeps trying to route through the (now offline) exit node. The setting is client-side. |
I didn’t have Tailscale SSH set up. I didn’t have a serial console password. I had no way in.
What I Had to Do
Delete the VM and start from scratch with a new one.
The Lesson
Always build your safety net before you walk the tightrope. Set up Tailscale SSH, set a serial console password, enable serial port access. All BEFORE you touch exit node routing. These take 2 minutes and save you from a full rebuild.
The second time, I did Phase 4 (safety nets) before Phase 6 (exit node), and it’s been running stable since.
Monitoring & Maintenance
Quick Check: Is the VPS Connected Through the Phone?
From your laptop:
ssh root@<VPS_TAILSCALE_IP> "curl -s --max-time 5 ifconfig.me" - Returns an IP like
182.253.x.x(phone’s IP) = connected - Hangs or times out = phone is down
Detailed Check: Connection Status
ssh root@<VPS_TAILSCALE_IP> "tailscale status | grep <PHONE_HOSTNAME>" active; exit node; direct= connected, working, best performanceactive; exit node; relay= connected but going through DERP relay (slower)idle; offers exit node; offline= phone is disconnected
If the Phone Goes Down
Temporarily disable the exit node to restore the VPS’s own internet:
ssh root@<VPS_TAILSCALE_IP> "sudo tailscale set --exit-node=" Re-enable once the phone is back:
ssh root@<VPS_TAILSCALE_IP> "sudo tailscale set --exit-node=<PHONE_HOSTNAME> --exit-node-allow-lan-access=true" Phone Optimization for 24/7 Operation
The phone needs to stay on and connected. Android aggressively kills background apps, so these settings are essential:
| Setting | Where | Why |
|---|---|---|
| Disable battery optimization for Tailscale | Settings > Apps > Tailscale > Battery > “Unrestricted” | Prevents Android from killing Tailscale in the background |
| Enable Always-on VPN | Settings > Network > VPN > Tailscale > “Always-on VPN” | Auto-reconnects if Tailscale drops |
| Disable “Remove permissions if unused” | Settings > Apps > Tailscale | Prevents Android from revoking permissions |
| Enable “Stay awake” (Developer Options) | Settings > System > Developer Options | Keeps screen on while charging |
| Keep phone plugged in | Physical | Battery drain is real when running as exit node |
| Connect to WiFi | Physical | More stable than mobile data, avoids data charges |
| Disable auto-updates | Play Store settings | Prevents unexpected restarts |
Note: Some phone brands (Xiaomi, Huawei, Samsung) have additional aggressive battery management. Check dontkillmyapp.com for phone-specific instructions.
Warning: Do NOT enable “Block connections without VPN” in the Always-on VPN settings. If Tailscale disconnects, the phone will lose all internet and can’t reconnect to Tailscale, creating a deadlock.
Pros & Cons
Pros
| Pro | Detail |
|---|---|
| Zero cost | Tailscale free tier (up to 100 devices). Phone already owned. No recurring charges. |
| Legitimate residential IP | The IP is genuinely residential. It’s your home ISP IP from your actual network. Nothing is spoofed. |
| No code changes | The application on the VPS doesn’t need any modification. Traffic routing happens at the OS/network level. |
| Encrypted tunnel | All traffic between VPS and phone is encrypted via WireGuard. Even your ISP can’t inspect the tunnel contents. |
| Easy setup | One install command on the VPS, one app on the phone. Tailscale handles NAT traversal, key management, and reconnects. |
| No static IP needed | The phone doesn’t need a static IP or port forwarding. Tailscale handles NAT punching automatically. |
| Direct connections | When both devices can punch through NATs, traffic goes peer-to-peer. No relay server in the middle. |
Cons
| Con | Detail | Severity |
|---|---|---|
| Phone must stay on 24/7 | If the phone dies, loses WiFi, or Android kills Tailscale, the VPS loses ALL internet connectivity, not just the residential IP. | High |
| Android kills background apps | Even with battery optimization disabled, some Android skins aggressively kill background processes. Requires ongoing vigilance. | Medium |
| Single point of failure | One phone, one exit node. No redundancy. If it goes down, everything stops. | High |
| Extra latency | All VPS traffic now has an extra hop through a phone on a home network. Adds ~10-50ms depending on connection quality. For most use cases (API calls, messaging) this is negligible. | Low |
gcloud compute ssh breaks | After enabling the exit node, regular SSH over the public internet stops working. Must use Tailscale SSH. | Medium |
| Phone IP may change | Your ISP may rotate your residential IP. This doesn’t break the tunnel (Tailscale handles reconnects), but the public-facing IP changes. Most services handle gradual IP changes fine. | Low |
| Android exit node performance | Tailscale’s docs note that “Android exit nodes use userspace routing with limited performance.” Fine for text-based workloads, not ideal for high-bandwidth use. | Low |
| DNS bug workaround needed | Android exit nodes have a known DNS issue requiring a global DNS override in the Tailscale admin console. Without the fix, connected devices lose internet entirely. | Medium |
| Lockout risk during setup | Misconfiguring the exit node can lock you out of the VPS completely. Safety nets (Tailscale SSH, serial console) must be set up first. | High (one-time) |
Honest Assessment
This is a creative, zero-cost solution that works well for personal projects and R&D. It is not production-grade infrastructure. The single point of failure (one phone) and the dependency on Android not killing the app make it unsuitable for anything that requires high availability.
For my use case, a personal AI assistant that can tolerate occasional downtime while I restart the phone or re-enable the exit node, it’s been perfectly fine. The setup has been running stable since I set it up.
If you need something more robust, consider:
- A dedicated Linux device (like a Raspberry Pi) at home running Tailscale as an exit node, far more reliable than Android
- A residential proxy service, costs money but zero maintenance
- The official API of whatever service you’re trying to talk to. If one exists, it’s always the best long-term answer.
Disclaimer
Networking is not my main domain. This was purely R&D on my end. Figuring things out as I went, breaking things, rebuilding, and documenting what I learned.
This guide reflects what worked for me in my specific setup (GCP VPS + Xiaomi Redmi Note 9 on Android 10). Your environment may have different quirks. The rp_filter fix, for example, was needed specifically on GCP Ubuntu 24.04. Other providers or OS versions may not need it.
If you spot anything that could be done better, or if you’ve found improvements to this setup, I’d genuinely love to hear about it. This is a living document, and feedback makes it better.
Sources
- Tailscale Exit Nodes Documentation
- Tailscale Download / Install
- Android Exit Node DNS Issue, GitHub #6119
tailscale setvstailscale up, GitHub #15460- Tailscale Android App Improvements
- Tailscale NAT Traversal in Cloud Environments
- Don’t Kill My App, Android Background App Restrictions
All the experiences in this post are real, but AI was involved in writing this blog. If anything seems off, feel free to let me know.