Skip to content

Instantly share code, notes, and snippets.

@mgregoro
Created February 5, 2017 06:53
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 mgregoro/9f3bc8eec382ab06e0aa9e2bab1ccbff to your computer and use it in GitHub Desktop.
Save mgregoro/9f3bc8eec382ab06e0aa9e2bab1ccbff to your computer and use it in GitHub Desktop.
convenience script for starting openvpn and update resolv.conf based on what was PUSHed by the server; handy on the *BSDs
#!/usr/bin/env perl
unless ($> == 0) {
die "Must run ovpn.pl as root!\n";
}
unless ($ARGV[0]) {
die "Usage: ovpn.pl <conf-file-in-cwd>\n";
}
my $conf_file = $ARGV[0];
if ($conf_file =~ /\//) {
die "[fatal] must run ovpn.pl from the config directory\n";
}
if ($conf_file =~ "random(?:-([A-Z]{2}))*") {
my (@confs, $country);
if ($country = $1) {
@confs = glob("ipvanish-$country*.ovpn");
} else {
@confs = glob("*.ovpn");
}
if (scalar(@confs) == 0) {
if ($country) {
die "[fatal] couldn't find any configs in country '$country' to choose from\n";
} else {
die "[fatal] couldn't find any configs to choose from\n";
}
}
my $chosen_idx;
my $rolls = int(rand(int($#confs / 8)));
for (my $i = 0; $i < $rolls; $i++) {
$chosen_idx = int(rand($#confs));
}
# the last roll is the config
$conf_file = $confs[$chosen_idx];
print "[random] randomly chose $conf_file\n";
}
my $perl_pid = $$;
my $dns_servers = [];
$SIG{ALRM} = sub {
return unless $$ == $perl_pid;
if (scalar(@$dns_servers)) {
print "@{[scalar localtime]} automatically generating resolv.conf from vpn PUSHed values\n";
system("mv -f /etc/resolv.conf /tmp/resolv.conf.$$.ovpnorig");
open my $rc, '>', '/etc/resolv.conf' or die "Can't open /etc/resolv.conf for writing: $!\n";
print $rc "# resolv.conf autogenerated by ovpn.pl at @{[scalar localtime ]}\n";
while (my $ns = shift @$dns_servers) {
print $rc "nameserver $ns\n";
}
} else {
warn "@{[scalar localtime]} - warning - dns_servers array was empty\n";
}
};
# clean up.
$SIG{INT} = $SIG{KILL} = $SIG{TERM} = \&cleanup;
# open VPN after signal handlers are installed.
open my $fh, '-|', "openvpn --config $conf_file";
while (my $line = <$fh>) {
if ($line =~ /PUSH:/) {
@dns_servers = ();
while ($line =~ /dhcp-option DNS ([\d\.]+)/g) {
push(@$dns_servers, $1);
}
alarm 3;
}
print "$line";
}
# openvpn died, clean up.
cleanup();
sub cleanup {
return unless $$ == $perl_pid;
if (-e "/tmp/resolv.conf.$$.ovpnorig") {
print STDOUT "@{[scalar localtime]} - exiting - restoring original resolv.conf\n";
system("mv -f /tmp/resolv.conf.$$.ovpnorig /etc/resolv.conf");
exit;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment