remoteme.pl (2201B)
1 #!/usr/bin/env perl 2 3 use Errno qw/ENODATA/; 4 use Getopt::Long qw/GetOptions/; 5 use STUN::Client; 6 use 5.010; # used in example in https://perlmaven.com/how-to-process-command-line-arguments-in-perl 7 use Data::Dumper; 8 use File::BaseDir qw/config_files/; 9 10 use constant DEFAULT_SERVER_LIST_PATH => '/usr/share/stun/servers.txt'; 11 12 my $_remotestring; 13 my $nonewline; 14 my $configfile; 15 GetOptions( 16 'd' => \$debug, 17 'n' => \$nonewline, 18 'host=s' => \$_remotestring, 19 'c=s' => \$configfile, 20 ); 21 22 if ($configfile eq '') { 23 $configfile = config_files('remoteme/servers.txt'); 24 } 25 26 if ($configfile eq '') { 27 if (! -f DEFAULT_SERVER_LIST_PATH) { 28 if ($_remotestring eq '') { 29 print STDERR qq{server list missing\n}; 30 exit 1; 31 } 32 } 33 $configfile = DEFAULT_SERVER_LIST_PATH; 34 } 35 36 my @servers; 37 if ($_remotestring) { 38 #$remotestring = $_remotestring; 39 push @servers, $_remotestring; 40 } else { 41 if ($debug) { 42 print STDERR "using config file " . $configfile . "\n"; 43 } 44 my $f; 45 open($f, "<", $configfile); 46 foreach my $l (<$f>) { 47 push @servers, $l; 48 } 49 close($f); 50 51 } 52 53 my $result; 54 foreach my $remotestring (@servers) { 55 my $host = $remotestring; 56 my $port = 3478; 57 if ($remotestring =~ ':') { 58 ($host, $port) = split(/:/, $remotestring); 59 } 60 61 if ($debug) { 62 print STDERR "using host " . $remotestring; 63 } 64 65 $c = STUN::Client->new; 66 67 eval { 68 $c->stun_server($host); 69 } or do { 70 exit $!; 71 }; 72 eval { 73 ($old, $new) = $c->get or die "cannot get $!"; 74 } and do { 75 undef $old; 76 $result = $new->{'attributes'}{'XOR-MAPPED-ADDRESS'}{'address'}; 77 if (!defined $new || $result eq '') { 78 exit ENODATA; 79 } 80 print $result; 81 unless ($nonewline) { 82 print "\n"; 83 } 84 #print Dumper($new); 85 exit 0; 86 }; 87 88 undef $old; 89 } 90 91 __END__ 92 93 =head1 NAME 94 95 rmme - Print current public internet address 96 97 =head1 SYNOPSIS 98 99 rmme [-nh] 100 101 =head1 DESCRIPTION 102 103 Queries a STUN server for the local host's public internet address and returns the result. 104 105 If no address is reported ENODATA will be returned. 106 107 =head1 OPTIONS 108 109 =over 2 110 111 =item -n Omit newline at end of result 112 113 =item -h Stun server hostname in format <host|ip>[:port] 114 115 =back 116 117 =head1 AUTHOR 118 119 Louis Holbrook <dev@holbrook.no> (https://holbrook.no) 120 121 =head1 COPYRIGHT 122 123 Licenced under GPLv3