#!/usr/bin/perl -Tw # amprroutes.pl V0.4 # This script generates router tunnel configurations for the AMPRNet # routes which can be loaded into various types of routers including # Cisco, Juniper, VyOS, or Linux. # Script created by Antonio Querubin AH6BW tony[at]lavanauts.org # Based on the encapconvert script created by Jason Begley KY9J ky9j.com # ky9j[at]arrl.net. use MIME::Base64; use LWP::UserAgent; use JSON; use Net::IP; my $url = 'https://portal.ampr.org/api/v1/encap'; my %nets = (); # IP object for each route. my %gateways = (); # Gateway for each route. my %routes = (); # List of routes for each gateway. my %gw2tunnel = (); # Tunnel ID for each gateway. my %tunnel2gw = (); # Tunnel ID to gateway map. my $net = undef; my $mask = undef; ##### # Below are user defined varibles my $username = 'ah6bw'; # AMPRNet portal username my $password = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; # Portal API key my $loop = 'loopback0'; # LOOPBACK INT CHANGE IF ALREADY IN USE my $picif = 'ip-0/2/0'; # Juniper Tunnel PIC my $amprgw = '169.228.66.251'; # amprgw.sysnet.ucsd.edu my $outip = '67.53.202.230'; # YOUR PUBLIC IP ADDRESS my $loopip = '44.14.0.1'; # YOUR AMPR IP ADDRESS my $type = 'vyos'; # Type of router. # EO user defined varibles ##### # Retrieve the portal encap data. my $request = LWP::UserAgent->new; my $response = $request->get($url, 'Authorization' => 'Basic ' . encode_base64("$username:$password") ); # Convert the retrieved JSON data to a list of associative arrays. #my $jtext = from_json( $response->content, { allow_nonref => 1 } ); #my @encap = @{ decode_json($jtext) }; my @encap = @{ decode_json($response->content) }; foreach (@encap) { $p = "$_->{network}/$_->{maskLength}"; $gw = $_->{gatewayIP}; $ip = new Net::IP $p || die; $prefix = $ip->prefix(); $nets{$prefix} = $ip; $gateways{$prefix} = $gw; if ( defined($routes{$gw}) ) { push @{ $routes{$gw} }, $p; $tunnelid = $gw2tunnel{$gw}; } else { $routes{$gw} = [ $p ]; # Generate a unique Tunnel ID for each gateway address. Junos # interface unit values cannot exceed 16385 (~ 2**14). So divide a # 32-bit address by 18 bits. Increment if it's not unique. $gwip = new Net::IP $gw || die; $gwint = $gwip->intip(); $tunnelid = $gwint / (2**18); while (defined($tunnel2gw{$tunnelid})) { $tunnelid++; } $gw2tunnel{$gw} = $tunnelid; $tunnel2gw{$tunnelid} = $gw; } $n = $ip->ip(); $s = $ip->prefixlen(); $mask = $ip->mask(); print "*ip info*\n"; print "NET:$n\nBITS:$s MASK:$mask\nGW:$gw\nIF:$tunnelid\n\n"; } foreach $tunnelid ( sort (keys %tunnel2gw) ) { print "$tunnel2gw{$tunnelid}: @{ $routes{ $tunnel2gw{$tunnelid} } }\n"; } open (MYFILE, ">ampr-tunnel-config.txt"); if ($type eq 'cisco') { print MYFILE "interface $loop\n"; print MYFILE " ip address $loopip 255.255.255.255\n\n"; print MYFILE "interface Tunnel1\n"; print MYFILE " description Default AMPRNet tunnel\n"; print MYFILE " ip unnumbered $loop\n"; print MYFILE " tunnel source $outip\n"; print MYFILE " tunnel destination 169.228.66.251\n"; print MYFILE " tunnel mode ipip\n"; print MYFILE "end\n\n"; } elsif ($type eq 'juniper') { print MYFILE "interfaces {\n"; print MYFILE " $picif {\n"; } elsif ($type eq 'vyos') { print MYFILE "set interfaces tunnel tun0 description 'AMPRNet UCSD gateway'\n"; print MYFILE "set interfaces tunnel tun0 encapsulation ipip\n"; print MYFILE "set interfaces tunnel tun0 local-ip 67.53.202.230\n"; print MYFILE "set interfaces tunnel tun0 remote-ip 169.228.66.251\n"; print MYFILE "set policy route net44pbr description 'AMPRNet policy routing'\n"; print MYFILE "set policy route net44pbr rule 10 set table 44\n"; } elsif ($type eq 'linux') { print MYFILE "ip tunnel add tunl0 mode ipip remote $amprgw local $outip\n"; print MYFILE "ifconfig tunl0 up\n"; print MYFILE "ip route add 44.0.0.0/8 via $amprgw dev tunl0 onlink\n"; } # Generate the tunnel interfaces for all gateways except our own. foreach $tunnelid (values %gw2tunnel) { $gw = $tunnel2gw{$tunnelid}; next if ($gw eq $outip); if (defined($debug)) { if ($type eq 'cisco') { print "\ninterface Tunnel$tunnelid\n"; print " description Link to $gw\n"; print " ip unnumbered $loop\n"; print " tunnel source $outip\n"; print " tunnel destination $gw\n"; print " tunnel mode ipip\n"; } elsif ($type eq 'juniper') { print " unit $tunnelid {\n"; print " description \"Link to $gw\";\n"; print " tunnel {\n"; print " source $outip;\n"; print " destination $gw;\n"; print " }\n"; print " family inet;\n"; print " }\n"; } elsif ($type eq 'vyos') { print "set interfaces tunnel tun$tunnelid description Link to $gw\n"; print "set interfaces tunnel tun$tunnelid encapsulation ipip\n"; print "set interfaces tunnel tun$tunnelid local-ip $outip\n"; print "set interfaces tunnel tun$tunnelid remote-ip $gw\n"; } } if ($type eq 'cisco') { print MYFILE "\ninterface Tunnel$tunnelid\n"; print MYFILE " description Link to $gw\n"; print MYFILE " ip unnumbered $loop\n"; print MYFILE " tunnel source $outip\n"; print MYFILE " tunnel destination $gw\n"; print MYFILE " tunnel mode ipip\n"; } elsif ($type eq 'juniper') { print MYFILE " unit $tunnelid {\n"; print MYFILE " description \"Link to $gw\";\n"; print MYFILE " tunnel {\n"; print MYFILE " source $outip;\n"; print MYFILE " destination $gw;\n"; print MYFILE " }\n"; print MYFILE " family inet;\n"; print MYFILE " }\n"; } elsif ($type eq 'vyos') { print MYFILE "set interfaces tunnel tun$tunnelid description 'Link to $gw'\n"; print MYFILE "set interfaces tunnel tun$tunnelid encapsulation ipip\n"; print MYFILE "set interfaces tunnel tun$tunnelid local-ip $outip\n"; print MYFILE "set interfaces tunnel tun$tunnelid remote-ip $gw\n"; } elsif ($type eq 'linux') { } } if ($type eq 'cisco') { print MYFILE "\n"; } elsif ($type eq 'juniper') { print MYFILE " }\n"; print MYFILE "}\n"; print MYFILE "routing-options {\n"; print MYFILE " static {\n"; } # Generate the static routes to each gateway. foreach $prefix (keys %nets) { $ip = $nets{$prefix}; $gw = $gateways{$prefix}; next if ($gw eq $outip); $net = $ip->prefix(); $n = $ip->ip(); $mask = $ip->mask(); $tunnelid = $gw2tunnel{$gw}; if ($type eq 'cisco') { print MYFILE "ip route $n $mask tunnel$tunnelid\n"; } elsif ($type eq 'juniper') { print MYFILE " route $net next-hop $picif.$tunnelid;\n"; } elsif ($type eq 'vyos') { print MYFILE "set protocols static table 44 interface-route $net next-hop-interface tun$tunnelid\n"; } elsif ($type eq 'linux') { print MYFILE "ip route add $net via $gw dev tunl0 onlink\n"; } } if ($type eq 'cisco') { print MYFILE "\nend\n"; } elsif ($type eq 'juniper') { print MYFILE " }\n"; print MYFILE "}\n"; }