Changeset a098fab
- Timestamp:
- Sep 16, 2007 8:33:38 PM (17 years ago)
- Branches:
- axis_example, compt_changes, info-ops, master, version-1.30, version-2.00, version-3.01, version-3.02
- Children:
- 3c7da22
- Parents:
- 321c0cb
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
fedkit/fed-tun.pl
r321c0cb ra098fab 6 6 # Set up ssh tunnel infrastructure for federation: 7 7 # 8 # * Set up the synchronization system 8 # * Parse the configuration file provided. 9 # 10 # * Figure out whether we're the initiator or the reciever; if we're 11 # the receiver, we just need to set up ssh keys and exit. 12 # 13 # * Pick out the experimental interface, remove the IP address 9 14 # 10 # * Figure out our location. 11 # From DETER: 12 # + bring up em0 and assign the appropriate address (with only one 13 # tunnel node, this'll be static) 14 # + ssh out to WAIL node using the experiment name, creating a tunnel 15 # for each of the experimental interfaces that is up (one, for now) 16 # 17 # From WAIL: 18 # + exit and wait for the ssh from DETER, which'll trigger the 19 # setup of everything else 20 # 21 # * pick out the experimental interface, remove the IP address 22 # 23 # * identify the tun interface created, and bridge it to the 24 # experimental interface 15 # * Create a layer 2 ssh tunnel, set up bridging, and hang loose. 25 16 26 17 use strict; … … 28 19 use POSIX qw(strftime); 29 20 use Sys::Hostname; 21 use IO::File; 30 22 31 23 my $TMCC = "/usr/local/etc/emulab/tmcc"; 32 24 my $SSH = "/usr/local/bin/ssh"; 33 my $HOME = "/users/lahey"; 34 35 # Where are we gonna get this info from!? Hardcoding is definitely not 36 # gonna happen! 37 38 my $tunnel_ip = "206.117.25.26"; 39 my $tunnel_iface = "em0"; 40 my $remote_node = "detertunnel."; 41 my $remote_node_domain = ".deter.emulab.net"; 42 my $ssh_port_fwds = "-R :139:users.isi.deterlab.net:139 -R :7777:boss.isi.deterlab.net:7777"; 43 25 my $NC = "/usr/bin/nc"; 26 my $SSH_PORT = 22; 27 28 sub setup_bridging; 29 sub setup_tunnel_cfg; 30 sub parse_config; 31 32 # Option use is as follows: 33 # -f filename containing config file 34 # -d turn on debugging output 35 # -r remotely invoked 36 # (if remotely invoked the last two args are the tun interface 37 # number and the remote address of the tunnel) 38 39 my $usage = "Usage: fed-tun.pl [-r] [-d] [-f config-filename] [count addr]\n"; 40 41 my %opts; 42 my $filename; 43 my $remote; 44 44 my $debug = 1; 45 my $remote;46 47 45 my $count; 48 46 my $addr; 49 47 50 sub find_new_tun; 51 sub setup_network($; $; $; $); 52 53 # Option use is as follows: 54 # -r remote execution on WAIL; set up as appropriate 55 56 my $usage = "Usage: fed-tun.pl [-t remote-testbed-fqdn] [-r hostname count]\n"; 57 58 my %opts; 59 if ($#ARGV != 0 && !getopts('rt:', \%opts)) { 48 if ($#ARGV != 0 && !getopts('df:r', \%opts)) { 60 49 die "$usage"; 61 50 } 62 51 63 64 if (defined($opts{'t'})) { 65 $remote_node_domain = $opts{'t'}; 52 if (defined($opts{'d'})) { 53 $debug = 1; 54 } 55 56 if (defined($opts{'f'})) { 57 $filename = $opts{'f'}; 66 58 } 67 59 … … 74 66 } 75 67 76 # Set up synchronization, so that the various user machines won't try to 77 # contact boss before the tunnels are set up. 78 79 # XXX: put off for now 68 die "$usage" if (!defined($remote) && !defined($filename)); 69 70 if (defined($filename)) { 71 &parse_config("$filename", \%opts) || 72 die "Cannot read config file $filename: $!\n"; 73 } 74 75 my $ssh_port_fwds = ""; 76 77 if (defined($opts{'fsname'})) { 78 $ssh_port_fwds = "-R :139:$opts{'fsname'}:139 "; 79 } 80 81 if (defined($opts{'bossname'})) { 82 $ssh_port_fwds .= "-R :7777:$opts{'bossname'}:7777 "; 83 } 84 85 $ssh_port_fwds = "" if ($opts{'type'} eq 'experiment'); 86 87 print "ssh_port_fwds = $ssh_port_fwds\n" if ($debug); 88 89 print "opts %opts\n"; 80 90 81 91 # Need these to make the Ethernet tap and bridge to work... … … 84 94 system("kldload /boot/kernel/if_tap.ko"); 85 95 86 # Ask tmcd to figure out experiment and project; these should 87 # be available as environment variables (PID, EID, and NODE) for 88 # a startup script, but if run explicitly, we might not have 'em. 89 90 my $project; 91 my $experiment; 92 my $node_id; 93 94 open(TMCD, "$TMCC status |") || die "tmcc failed\n"; 95 while (<TMCD>) { 96 print if ($debug); 97 if (/ALLOCATED=([\w\-]+)\/([\w\-]+) NICKNAME=([\w\-]+)/) { 98 $project = $1; 99 $experiment = $2; 100 $node_id = $3; 101 } 102 } 103 close(TMCD); 104 105 die "Didn't find experiment or project name\n" if (!$project || !$experiment); 106 107 print "project $project experiment $experiment node $node_id\n" if ($debug); 108 109 110 # Figure out whether we're sourcing the tunnel or sinking it. For now 111 # I'll do something ugly and use the hostname. 112 113 my $hostname = hostname(); 114 my @names = split(/\./, $hostname); 115 116 if ($#names > 1) { 117 my $domain = $names[$#names - 1]; 118 if (!$remote && $domain ne "deterlab") { 119 # Fix up ssh (ugh!) 120 system("sed 's/tunnel.simplefed/wailtunnel.$experiment/' $HOME/root-id_rsa.pub >> /root/.ssh/authorized_keys"); 121 die "Not on DETER; exiting for now\n"; 122 } 123 } else { 124 die "Failed to find a name for this host; exiting\n"; 96 if ($opts{'tunnelcfg'} && !$remote) { 97 # Most Emulab-like testbeds use globally-routable addresses on the 98 # control net; at DETER, we isolate the control net from the Internet. 99 # On DETER-like testbeds, we need to create special tunneling nodes 100 # with external access. Set up the external addresses as necessary. 101 &setup_tunnel_cfg(%opts); 125 102 } 126 103 127 104 if (!$remote) { 128 # If we're at DETER, open up a separate tunnel to the remote host for 129 # each of the different experiment net interfaces on this machine. 130 # Execute this startup script on the far end, but with the -r option 131 # to indicate that it's getting invoked remotely and should start 132 # setting up. 133 134 # Lame DETER setup hacks: 135 136 system("ifconfig $tunnel_iface $tunnel_ip"); 137 system("route add -net 198.133.225.59 -netmask 0xffffff00 206.117.25.1"); 138 system("route add -net 155.98.33.0 -netmask 0xfffff000 206.117.25.1"); 139 system("route add 128.9.160.161 206.117.25.1"); 140 141 # XXX: fix up ssh. Ugh. 142 143 system("cp $HOME/root-id_rsa /root/.ssh/id_rsa"); 144 system("cp $HOME/root-id_rsa.pub /root/.ssh/id_rsa.pub"); 105 system("umask 077 && cp $opts{'privkeys'} /root/.ssh/id_rsa"); 106 system("umask 077 && cp $opts{'pubkeys'} /root/.ssh/id_rsa.pub"); 107 system("umask 077 && cat $opts{'pubkeys'} >> /root/.ssh/authorized_keys"); 108 } 109 110 if ($opts{'active'}) { 111 # If we're the initiator, open up a separate tunnel to the remote 112 # host for each of the different experiment net interfaces on this 113 # machine. Execute this startup script on the far end, but with 114 # the -r option to indicate that it's getting invoked remotely and 115 # we should just handle the remote-end tasks. 116 117 # Set up synchronization, so that the various user machines won't try to 118 # contact boss before the tunnels are set up. (Thanks jjh!) 119 120 do { 121 system("$NC -z $opts{'peer'} $SSH_PORT"); 122 } until (!$?); 145 123 146 124 # XXX: Do we need to clear out previously created bridge interfaces? 147 125 148 my $remote_name = $remote_node . $experiment . $remote_node_domain;149 126 my $count = 0; 127 my @SSHCMD; 150 128 151 129 open(IFFILE, "/var/emulab/boot/ifmap") || die "couldn't open ifmap\n"; … … 159 137 print "Found $iface, $addr, to bridge on $bridge\n" if ($debug); 160 138 161 system("$SSH -w $count:$count $ssh_port_fwds $remote_name \"$HOME/fed-tun.pl -r $addr $count\" &");162 163 # XXX: Ack, ssh will never return, since it's doing tunneling.164 # Unfortunately, though, it also could take quite a few seconds165 # to do the DNS lookup and actually run the command on the 166 # other side. Hence, the delay. Shudder:167 168 sleep 10;169 170 setup_network($tun, $bridge, $iface, $addr);139 # Note that we're going to fire off an ssh which will never return; 140 # we need the connection to stay up to keep the tunnel up. 141 # In order to check for problems, we open it this way and read 142 # the expected single line of output when the tunnel is connected. 143 144 open($SSHCMD[$count], "$SSH -w $count:$count $ssh_port_fwds -o \"StrictHostKeyChecking no\" $opts{'peer'} \"./fed-tun.pl -r $addr $count\" |") or die "Failed to run ssh"; 145 146 my $check = <$SSHCMD[$count]>; # Make sure something ran... 147 148 &setup_bridging($tun, $bridge, $iface, $addr); 171 149 $count++; 150 $ssh_port_fwds = ""; # only do this on the first connection 172 151 } 173 152 close(IFFILE); 174 } els e{153 } elsif ($remote) { 175 154 # We're on the remote system; for now, we just grab and use 176 155 # the one experimental interface. Later, we'll actually look … … 188 167 my $tun = "tap" . $count; 189 168 190 setup_network($tun, $bridge, $iface, $addr);169 &setup_bridging($tun, $bridge, $iface, $addr); 191 170 $iter++; 192 171 } 193 172 close(IFFILE); 173 174 print "Remote connection all set up!\n"; # Trigger other end with output 175 } else { 176 print "inactive end of a connection, finishing" if ($debug); 194 177 } 195 178 … … 197 180 exit; 198 181 199 # XXX: Unused. Find the name of the new tunnel interface200 201 my %tuns_used;202 203 sub find_new_tun {204 my @tuns = split(/ /, `ifconfig -l`);205 my $tun;206 207 print @tuns . "\n";208 209 foreach my $tun (@tuns) {210 print "Looking at $tun\n";211 if (!$tuns_used{$tun}) {212 $tuns_used{$tun} = 1;213 print "Found $tun\n";214 return $tun;215 }216 }217 }218 182 219 183 # Set up the bridging for the new stuff... 220 184 221 sub setup_ network($; $; $; $) {185 sub setup_bridging($; $; $; $) { 222 186 my ($tun, $bridge, $iface, $addr) = @_; 223 187 … … 230 194 system("ifconfig $bridge addm $tun"); 231 195 } 196 197 # Set up tunnel info for DETER-like testbeds. 198 199 sub setup_tunnel_cfg { 200 my (%opts) = @_; 201 my $tunnel_iface = "em0"; # XXX 202 my $tunnel_ip; 203 my $tunnel_mask; 204 my $tunnel_mac; 205 my $tunnel_router; 206 207 print "Opening $TMCC tunnelip\n" if ($debug); 208 209 open(TMCD, "$TMCC tunnelip |") || die "tmcc failed\n"; 210 print "Opened $TMCC tunnelip\n" if ($debug); 211 while (<TMCD>) { 212 print "got one line from tmcc\n" if ($debug); 213 print if ($debug); 214 if (/^TUNNELIP=([0-9.]*) TUNNELMASK=([0-9.]*) TUNNELMAC=(\w*) TUNNELROUTER=([0-9.]*)$/) { 215 $tunnel_ip = $1; 216 $tunnel_mask = $2; 217 $tunnel_mac = $3; 218 $tunnel_router = $4; 219 } 220 } 221 close(TMCD); 222 223 die "Unable to determine tunnel node configuration information" 224 if (!defined($tunnel_router)); 225 226 print "tunnel options: ip=$tunnel_ip mask=$tunnel_mask mac=$tunnel_mac router=$tunnel_router\n" if ($debug); 227 228 # Sadly, we ignore the tunnel mac for now -- we should eventually 229 # use it to determine which interface to use, just like the 230 # Emulab startup scripts. 231 232 system("ifconfig $tunnel_iface $tunnel_ip" . 233 ($tunnel_mask ? " netmask $tunnel_mask" : "")); 234 warn "configuration of tunnel interface failed" if ($?); 235 236 system("route add $opts{'peer'} $tunnel_router"); 237 warn "configuration routes via tunnel interface failed" if ($?); 238 239 print "setup_tunnel_cfg done\n" if ($debug); 240 } 241 242 # Trick config-file parsing code from Ted Faber: 243 244 # Parse the config file. The format is a colon-separated parameter name 245 # followed by the value of that parameter to the end of the line. This parses 246 # that format and puts the parameters into the referenced hash. Parameter 247 # names are mapped to lower case, parameter values are unchanged. Returns 0 on 248 # failure (e.g. file open) and 1 on success. 249 sub parse_config { 250 my($file, $href) = @_; 251 my($fh) = new IO::File($file); 252 253 unless ($fh) { 254 warn "Can't open $file: $!\n"; 255 return 0; 256 } 257 258 while (<$fh>) { 259 next if /^\s*#/ || /^\s*$/; # Skip comments & blanks 260 chomp; 261 /^([^:]+):\s*(.*)/ && do { 262 my($key) = $1; 263 264 $key =~ tr/A-Z/a-z/; 265 $href->{$key} = $2; 266 next; 267 }; 268 warn "Unparasble line in $file: $_\n"; 269 } 270 $fh->close(); # It will close when it goes out of scope, but... 271 return 1; 272 }
Note: See TracChangeset
for help on using the changeset viewer.