hetzneronline / community-content

Hetzner Online Community Project
https://community.hetzner.com
MIT License
298 stars 360 forks source link

How to protect a website with Cloudflare without exposing ports to the Internet #832

Closed JenoDK closed 5 months ago

JenoDK commented 5 months ago

Problem

The firewall for the cloudflare ip's is just for the ipv4 ips, it seems they now use their ipv6 ips.

Suggested Fix

Adjust the script to include the v6 ips.

import requests
import json

HETZNER_API_TOKEN = "YOUR_HETZNER_API_TOKEN"
HETZNER_FIREWALL_ID = "YOUR_HETZNER_FIREWALL_ID"
def get_cloudflare_ips(version):
    url = "https://www.cloudflare.com/ips-v" + version
    print("Getting ips from " + url)
    response = requests.get(url)
    if response.status_code == 200:
        return response.text.strip().split('\n')
    else:
        print("Failed to retrieve Cloudflare IP ranges")
        return []

def whitelist_ips_in_hetzner(ip_ranges):
    headers = {
        'Authorization': f'Bearer {HETZNER_API_TOKEN}',
        'Content-Type': 'application/json',
    }
    payload = {
        "rules": [
            {
                "direction": "in",
                "source_ips": ip_ranges,
                "port": "443",
                "protocol": "tcp",
                "description": "Accept port 443"
            },
            {
                "direction": "in",
                "source_ips": ["0.0.0.0/0","::/0"],
                "port": "22",
                "protocol": "tcp",
                "description": "Accept SSH connections"
            }
        ]
    }

    response = requests.post(f'https://api.hetzner.cloud/v1/firewalls/{HETZNER_FIREWALL_ID}/actions/set_rules', headers=headers, data=json.dumps(payload))
    if 200 <= response.status_code < 203:
        print("IPs whitelisted successfully in Hetzner Firewall")
    else:
        print("Failed to whitelist IPs in Hetzner Firewall", response.json())

if __name__ == "__main__":
    cloudflare_ips_v4 = get_cloudflare_ips("4")
    cloudflare_ips_v6 = get_cloudflare_ips("6")
    combined_ips = cloudflare_ips_v4 + cloudflare_ips_v6
    print("Whitelisting these ips:")
    for ip in combined_ips:
        print(ip)
    whitelist_ips_in_hetzner(combined_ips)
svenja11 commented 5 months ago

Thank you for your suggestion @JenoDK!