Skip to content

Instantly share code, notes, and snippets.

@walkure
Created May 16, 2023 13:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save walkure/0b86ce705eeae8ba82c862db701a84ea to your computer and use it in GitHub Desktop.
Save walkure/0b86ce705eeae8ba82c862db701a84ea to your computer and use it in GitHub Desktop.
Set Cloudflare IP Addresses to ipset and real_ip(nginx)
#!/usr/bin/env perl
use strict;
use warnings;
use HTTP::Tiny;
use Digest::MD5 'md5_hex';
my $prefix = 'cloudflare-origin';
updatelist('v4');
updatelist('v6');
die "ERR: requires one argument: output file path" unless scalar @ARGV == 1;
my $target=$ARGV[0];
my $old = load_old();
my $new = update();
#print "NEW:$new,OLD:$old\n";
if($old eq $new){
print "cloudflare address range not change\n";
}else{
system('nginx -t');
die "failure to validate nginx configure:$?" if $? != 0;
system('systemctl reload nginx');
die "failure to reload nginx configure:$?" if $? != 0;
print "reload nginx\n";
}
sub updatelist
{
my $type = shift;
my $family = $type eq 'v6' ? 'inet6' : 'inet';
my @addrs = fetch($type);
die "failure to fetch ipset addrs source" unless @addrs;
my $set = "$prefix-$type";
my $newset = "$set-tmp";
`ipset create $newset hash:net family $family`;
foreach my $addr(@addrs){
`ipset add $newset $addr`;
}
`ipset swap -q $set $newset`;
`ipset rename $newset $set` if $?;
`ipset destroy -q $newset`;
}
sub load_old
{
return "" unless -e $target;
open(my $fh,$target) or die "cannot open $target:$!";
my $old = <$fh>;
close $fh;
chomp $old;
substr($old,6);
}
sub update
{
my (@addrs) = fetch('v4');
my (@v6) = fetch('v6');
push(@addrs,@v6);
my $hash = md5_hex(@addrs);
open(my $fh,">$target") or die "cannot open $target:$!";
print $fh "#hash:$hash\n";
# ngx_http_realip_module
foreach my $addr(@addrs){
print $fh "set_real_ip_from $addr;\n";
}
print $fh "real_ip_header CF-Connecting-IP;\n";
close $fh;
$hash;
}
sub fetch
{
my $type = shift;
my $client = HTTP::Tiny->new();
my $res = $client->get("https://www.cloudflare.com/ips-$type");
if(!$res->{success}){
die "failure to fecth $type:$res->{reason}\n";
}
split(/\n/,$res->{content});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment