Skip to content

Instantly share code, notes, and snippets.

@Tugzrida
Last active August 7, 2022 14:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tugzrida/5910e1b1a9d096e297e793890b7c5236 to your computer and use it in GitHub Desktop.
Save Tugzrida/5910e1b1a9d096e297e793890b7c5236 to your computer and use it in GitHub Desktop.
nginx realip updater for Cloudflare
#!/usr/bin/python3
# v0.5 Created by Tugzrida(https://gist.github.com/Tugzrida/5910e1b1a9d096e297e793890b7c5236)
# This script should be added to the root crontab (or whichever user controls nginx)
# to run perhaps once or twice a day. It will create and keep up to date
# the file /etc/nginx/conf.d/cloudflare_realip.conf which will make all of nginx
# trust and use Cloudflare's provided client IP's.
#
# After updating the file, it runs nginx -t to check the config for errors, and if
# any are found, nginx will not be restarted to avoid taking things down. You may wish
# to add your own error reporting to the handle_error function below.
from urllib.request import urlopen
from urllib.error import URLError
from json import load
from os import system
def handle_error(e):
# Add your error reporting here
raise SystemExit(e)
try:
res = load(urlopen("https://api.cloudflare.com/client/v4/ips"))
if not res.get("success"):
raise URLError("Request not successful")
res = res["result"]
if not (res.get("etag") and res.get("ipv4_cidrs") and res.get("ipv6_cidrs")):
raise KeyError
except (URLError, ValueError, KeyError):
handle_error("Error loading Cloudflare IPs")
try:
with open("/etc/nginx/conf.d/cloudflare_realip.conf", "r") as f:
if f.readline().strip() == "#{}".format(res["etag"]):
print("No change. Exiting...")
raise SystemExit
except OSError:
# File doesn't exist yet
pass
print("IPs changed. Updating...")
newfile = '''#{}
############## THIS FILE IS AUTOMATICALLY GENERATED ##############
# This is a list of Cloudflare's IP addresses, which will supply a 'CF-Connecting-IP' header
# containing the proxied client's IP. These options tell nginx about this header and to trust it only
# from Cloudflare's IP's, thereby correcting all further references(logs, PHP, access control, etc.)
# to client IP to be the actual client's IP and not the proxy's IP.
real_ip_header CF-Connecting-IP;
'''.format(res["etag"])
for ip in res["ipv4_cidrs"] + res["ipv6_cidrs"]:
newfile += "set_real_ip_from {};\n".format(ip)
try:
with open("/etc/nginx/conf.d/cloudflare_realip.conf", "w") as f:
f.write(newfile)
except OSError:
handle_error("Cannot write to /etc/nginx/conf.d/cloudflare_realip.conf. Aborting")
if system("nginx -t") == 0:
system("service nginx reload")
else:
handle_error("Nginx config error! Not restarting")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment