Serving SSH sessions Ken Yap, kenUNDERSCOREyap AT users PERIOD sourceforge PERIOD net 7 January 1999 This document shows how to provide a login session that directly con- nects to remote hosts with SSH. I wanted a login program that would connect the user directly to a remote host with SSH. At first I thought of writing my own login program, then I remembered that mgetty could be configured to call any login program. So here's what I did: In /etc/mgetty+sendfax/login.config I added the line: ______________________________________________________________________ *@* sshguest @ /usr/local/etc/mgetty-ssh @ ______________________________________________________________________ In /etc/inittab I added the line: ______________________________________________________________________ 8:35:respawn:/sbin/mgetty -r tty8 ______________________________________________________________________ I picked a free virtual tty, you may want to expand this to other ttys later. In /etc/mgetty+sendfax/mgetty.config I added the lines: ______________________________________________________________________ port tty8 toggle-dtr n ignore-carrier y blocking y direct y login-time -1 ______________________________________________________________________ Thanks to Gert Doering (mgetty author) for the advice on the above settings. I added this user to /etc/passwd: ______________________________________________________________________ sshguest:*:199:199:SSH guest:/tmp: ______________________________________________________________________ If you are using shadow passwords you should also add an entry to /etc/shadow. The mgetty-ssh Perl script mentioned above is: ______________________________________________________________________ #!/usr/bin/perl die "No argument\n" if !defined($ARGV[0]); ($name, $host) = split /@/, $ARGV[0]; # remove leading non-alphanums from name and host to prevent # masquerading as arguments $name =~ s/^[^a-z0-9]*//; $host =~ s/^[^a-z0-9]*//; # remove whitespace as well $name =~ s/[ \t\f]//g; $host =~ s/[ \t\f]//g; # limit length of strings $name = substr($name, 0, 64); $host = substr($host, 0, 256); # do we have anything left? die "Name or host null\n" if ($name eq '' or $host eq ''); exec '/usr/bin/ssh', '-e', 'none', '-o', 'FallBackToRsh=no', '-o', 'StrictHostKeyChecking=yes', '-l', $name, $host; ______________________________________________________________________ Make sure this script is executable. If you are concerned that Perl takes up too much resources for a transient script, feel free to write the C equivalent. Make sure any remote hosts you want to connect to have their public keys in /etc/ssh/ssh_known_hosts Now on tty8 enter user@remote as the login name. You will get the following: ______________________________________________________________________ Red Hat Linux release 5.2 (Apollo) Kernel 2.0.36 on an i486 login: user@remote user@remote's password: Last login: Fri Dec 25 10:34:12 1998 from xterm.foo.com.au No mail. [user@remote user]$ ______________________________________________________________________ After I did this for mgetty, Peter Samuel pointed me to rungetty which is essentially an enhanced mingetty but can invoke programs other than login. Unlike mgetty, rungetty does not have any pattern matching facilities on the login name or indeed any means of passing the login name to the script. We get around this by prompting for the name in the script itself. In /etc/inittab, add the line: ______________________________________________________________________ 8:35:respawn:/usr/local/sbin/rungetty -u sshguest tty8 -- /usr/local/etc/rungetty-ssh ______________________________________________________________________ The rungetty-ssh script is essentially the same as the mgetty-ssh script but with a section to prompt for the login name: ______________________________________________________________________ #!/usr/bin/perl $| = 1; do { print "SSH to user\@host: "; } while (!defined(sysread(STDIN, $_, 100))); chomp($_); ($name, $host) = split /@/, $_; # remove leading non-alphanums from name and host to prevent # masquerading as arguments $name =~ s/^[^a-z0-9]*//; $host =~ s/^[^a-z0-9]*//; # remove whitespace as well $name =~ s/[ \t\f]//g; $host =~ s/[ \t\f]//g; # limit length of strings $name = substr($name, 0, 64); $host = substr($host, 0, 256); # do we have anything left? die "Name or host null\n" if ($name eq '' or $host eq ''); exec '/usr/bin/ssh', '-e', 'none', '-o', 'FallBackToRsh=no', '-o', 'StrictHostKeyChecking=yes', '-l', $name, $host; ______________________________________________________________________ The disadvantage is that when the prompt is active, this Perl script is always running. This offsets the gains made by using the lighter rungetty in place of mgetty. You may prefer to rewrite this in C to keep it very light. This technique could be used on diskless workstations to provide login sessions to remote hosts.