serverfault.com post outlined how you can use Cloudflare's API to query for your Origin IP and use that for SSH. However, they didn't account for multiple Zones, and they didn't account for SSH'ing to subdomains like
foo.example.com (though nor do I for now).
Cloudflare is both a DNS service and HTTPS reverse proxy. You can "gray-cloud" your DNS entries such that querying them will return your "real" (typically called Origin IP). But Cloudflare is at its best when you "orange-cloud" your DNS entries, which actually returns IP addresses owned by Cloudflare that then perform a reverse proxy to your Origin.
The protection here is at least two-fold:
- Your Origin IP is not revealed
- Cloudflare absorbs malicious traffic inbound for your service
But orange-clouds have their own set of problems. Namely, a limited set of ports are actually proxied to your Origin, and even then only for HTTPs.
SSH'ing to your domain names won't work
Imagine you own
example.com at IP
184.108.40.206 and expose both HTTP/S (TCP 80 and 443) and SSH (TCP 22) services. You'd probably access HTTPS and SSH via:
# Works, as example.com resolves to your Origin IP (220.127.116.11), and # you expose TCP 80 & 443. $ curl -v example.com * Connected to example.com (18.104.22.168) port 80 (#0) # Works, as example.com resolves to your Origin IP (22.214.171.124), and # you expose TCP 22. $ ssh -v example.com debug1: Connecting to example.com [126.96.36.199] port 22. debug1: Connection established.
But when you move to Cloudflare with an orange-cloud, you'll notice that non-HTTPS and non-proxied ports traffic no longer works:
# Works, as example.com resolves to Cloudflare IPs (188.8.131.52), and # they expose TCP 80 and 443 $ curl -v example.com * Connected to example.com (184.108.40.206) port 80 (#0) # Busted, as example.com resolves to Cloudflare IPs (220.127.116.11), and # they don't proxy TCP 22 $ ssh -v example.com debug1: Connecting to example.com [18.104.22.168] port 22. debug1: connect to address 22.214.171.124 port 22: Connection timed out ssh: connect to host example.com port 22: Network is unreachable
- Hardcode your Origin IP:
- Add gray-clouded subdomain:
- Use Cloudflare API to resolve your Origin IP.
Hardcode your Origin IP
You can still SSH to your Origin by using its IP address:
# Works because this is direct access, bypassing Cloudflare $ ssh -v 126.96.36.199 debug1: Connecting to 188.8.131.52 [184.108.40.206] port 22. debug1: Connection established.
But the downsides are:
- You must remember or write down your Origin IP
- If your Origin IP changes, you must manually update it
You could use a subdomain whose sole purpose is to provide "traditional" DNS resolution by using a gray-cloud and
CNAME'ing it to your Origin IP.
example.com will return Cloudflare's IPs, and connections will still be proxied. But
noproxy.example.com will return your Origin's IP, and connections will not be proxied:
# Works, proxied through Cloudflare $ curl -v example.com * Connected to example.com (220.127.116.11) port 80 (#0) # Works, no proxy through Cloudflare, connects directly to your Origin $ curl -v noproxy.example.com * Connected to example.com (18.104.22.168) port 80 (#0) # Works, no proxy through Cloudflare, connects directly to your Origin $ ssh -v noproxy.example.com debug1: Connecting to noproxy.example.com [22.214.171.124] port 22. debug1: Connection established.
The downsides are:
- Cloudflare is providing no security
- You reveal your Origin IP to anyone who queries for
Since Cloudflare has an API, and it knows your Origin IP in order to reverse proxy incoming connections, you can ask Cloudflare for your Origin IP before setting up an SSH connection.
This means you can retain your orange-cloud status, along with hiding your Origin IP to the public and leverage Cloudflare's security!
With that in mind, there are ~2 API calls to make in order to get the necessary information, both of which require API Permissions:
- Find example.com's Zone ID (
- Use example.com's Zone ID to lookup the Origin IP address for the root domain (
I decided to allow this API Token to work for all my Zones, but you can restrict its scope to all Zones belonging to a specific account, or even a list of single Zones.
Note: You could skip creating this API Token and use your Global API Key instead, but I would advise against it. Your Global API Key is akin to your account's password, and using this scoped API Token is following the principle of least privilege.
Using the Github Gist from above, and the
# Get Origin IP $ IP=$(cforigin example.com) && echo $IP 126.96.36.199 # SSH to Origin $ ssh -v $IP debug1: Connecting to 188.8.131.52 [184.108.40.206] port 22. debug1: Connection established.
- There can be more than one IP address that represents "Origin", as exampled in the Github Gist. It is up to the user to select the "correct" one to use.
cforigincurrently doesn't support
CNAME'd subdomains. If you wanted to connect to
foo.example.com, the API calls currently do not resolve this.
cforigincurrently doesn't support more than 2 top-level domains (TLDs). For instance,
example.com.ukwill incorrectly attempt to resolve