------------------------------------------------------------------------------- See also "usage/ssh_howto.txt" And for using SSH public keys with pass-phrase protection see And Kimmo Suominen's Guide... http://kimmo.suominen.com/docs/ssh/ ------------------------------------------------------------------------------- SSH versions (protocols and implementation) First there are two protocols v1 and v2 The first is insecure and is NOT used anymore, anywhere. (Just as: telnet, rsh, and non-anoymous ftp; is should not be used) The other distiction is Comercial SSH and OpenSSH which are just different implementations, with the biggest difference being how keys are stored on disk and in homes. (see below) SunSSH v3 is basied on OpenSSH, but with some slight differences in command line options. Caution is needed for advanced scripts. ------------------------------------------------------------------------------- Ssh Public Private Key Generation (no passphrase) SSH Version 1 Run the command, press return for all questions ssh-keygen To allow this account to access another account without a password append the file ".ssh/identity.pub" into ".ssh/authorized_keys" on the account you which access. These keys are opsolete and only the version 2 DSA keys are now needed. OpenSSH Three keys should be generated for maximum interoperatibility. ssh-keygen -t rsa1 ssh-keygen -t rsa ssh-keygen -t dsa Then for remote account access append the files ".ssh/id*.pub" into ".ssh/authorized_keys" on the remote account. Which key is used depends on the particular setup of the SSH daemond on both systems. Actually under open ssh you can also place authorized keys into the ".ssh/authorized_keys2" file as well. I use the normal file for my may autorization access from my primary accounts, while I use the second file as a local autorization file which is NOT distributed from my primary hosts. All OpenSSH stuff is saved into ".ssh" in your home. Commercial SSH2 The commerical SSH2 keys are generated as above, but are stored in the ".ssh2" sub-directory and used differently (extra level of indirection). * ssh-keygen is used to generate the public and private key files EG it generates files: id_dsa_1024_a id_dsa_1024_a.pub Rename to match host: id_dsa_kraken id_dsa_kraken.pub * .ssh2/identification then specifies the private key files, that identify this account to other accounts. EG: IdKey id_dsa_kraken * .ssh2/authorization contains lines identify public key files in the ".ssh2" sub-directory which are allowed access. EG: Key id_dsa_kobold.pub All SSH2 stuff is saved into ".ssh2" in your home. As such OpenSSH and SSH2 can happilly co-exist. OpenSSH and SSH2 key conversion To convert a OpenSSH public key to SSH2 (using OpenSSH) ssh-keygen -e -f .ssh/id_dsa.pub > .ssh2/id_dsa_`uname -n`.pub To convert SSH2 public key to OpenSSH authorized keys (using OpenSSH) ssh-keygen -i -f ~/.ssh2/id_dsa_`uname -n`.pub >> ~/.ssh2/authorized_keys Now you can then add that file name to the ".ssh2/authorization" file and copy both to the machine you want to login to without a password. echo "Key id_dsa_`uname -n`.pub" >> .ssh2/authorization NOTE: the base64 encoded key block does NOT care where the key is broken by newlines or spaces, so you can format it almost anyway you like, if the newlines are permitted by that file. The comment and subject fields seem to be freeform to identify which public key this file contains. ------------------------------------------------------------------------------- Ssh options on the command line... Due to problems with some programs (like rsync, see "rsync.hints", in this directory), most ssh programs will alow you to specify a "=" instead of a space between option and its argument. (Only openssh-2.1 does not seem to allow this which caused some problems). As such in scripts you can use... ssh -f -x -o BatchMode=yes {remote_command} Which turns off any password interaction with user (abort instead) The -f means to background the command and -x ensures an X window connection is also not setup. ------------------------------------------------------------------------------- Copying a file with a ':' in its name The following will fail as their is no host named "t" scp t:t remote: To fix you must have a '/' somewhere before the colon, in which case ssh will consider it a filename. EG: use any of the following... scp ./t:t remote: scp /path/to/file/t:t remote: =============================================================================== Special Techniques and Methods... ------------------------------------------------------------------------------- SSH Path and environment Check what path is used on the remote server and that their is no other junk... ssh remote.domain 'echo $PATH' or the rest of the envionment ssh remote.domain env You can override the initial ssh path my adding it to ".ssh/environment" on the remote server, but this only works if "PermitUserEnvironment" is set to true in the "/etc/ssh/sshd_config" file. echo "PATH=$PATH" >>~/.ssh/environment If this is not posible you can try something like... ssh remote.domain /bin/sh -c 'export PATH=$PATH_FROM_PROFILE; cmd' And debug with... ssh localhost 'pstree -p $$' ssh localhost /bin/sh -c 'pstree -p $$' ... and so on ... Note that better way of setting the environment is to use the shell and not the ssh, or the remote command. The t/csh will read the ".cshrc" file which can abort early for non-interactive commands. The bash shell will read ".bashrc" file (only time it does so), for non-interactive shells. ------------------------------------------------------------------------------- Ssh Server, Limit what commands will work... In the ".ssh/authorized_keys" file you can define a key as command="/path/to/some/command args..." ssh-dss ... Ensure it remains all on one line. This will force ssh to only execute the command that was given, and NOT the command actually requested by the client. Example commands... /usr/bin/cvs server only allow cvs upload/download /usr/bin/ssh user@host always forward user to another host The 'command' can be a special script that looks at the user requested command saved by SSH into the environment variable SSH_ORIGINAL_COMMAND, and then determines the appropriate course of action. For example, see my "ssh_restricted" script that restricts commands to specific directory of pre-defined commands. However the SSH_ORIGINAL_COMMAND envvar losses all the original quoting and escaping of the command and arguments. This means that any escaped or quoted white space, and other special shell characters, will loose there normal interpretation, unless the user provides further escaped quoting of the arguments. In other words do not just execute the provided command but parse it to ensure that things are what you want to allow the user to run. Examples of use. * Limit remote commands to specific ones * Parse rsync requests for `funny business and/or source requests * Log what commands are being requested for remote execution. ------------------------------------------------------------------------------- Encrypted links (for any service) ssh -L X:destination:Y firewall This will create a local port X which forwards connections and data to the machine "firewall", and then on to port Y on "destination". A client program (application) can then connect to "localhost:X" to contact the server at "destination:Y". The server program on "destination:Y" however will see the traffic from your client program coming from the machine "firewall", even though client is not actually running on that machine. In other words it sets up a link between the local machine and the one on "firewall" such that "localhost:X" delivers to "destination:Y" via that firewall host. Communications links... ssh -L X:destination:Y firewall "client prog" -normal-> "localhost:X" ====ssh encrypted====> "firewall" -normal-> "destination:Y" (server program) For a example of this see http://www.uk.research.att.com/vnc/sshvnc.html Add a -C (+C in ssh2) to compress the link as well as encrypt it. A extra -N option means no remote command or login is needed, just the link. NOTE: by default the "X" port is only linked to the loopback interface. This means only client programs on the local machine can use it. If you like client programs on another machine on your network to use port "X" on the initial machine, then also add the option "-o GatewayPorts=yes" or -g. Note: that as long as "localhost" and "firewall" has SSH, then either client or sever application, can be running on a window machine, not just UNIX, or linux! Also note that the links between the client and server applications and the SSH link ports are NOT encrypted, so should be kept local, or at least on the same subnet. The -R option is the same as -l except that the client / server positions are swicthed. EG: X is the port on the remote machine clients connect to while destination and Y is where the local machine transfers connections. Communications links... ssh -R X:destination:Y firewall "client prog" -normal-> "firewall:X" ====ssh encrypted====> "localhost" -normal-> "destination:Y" (server program) if the client connecting to the remote system is not local, then you must do add "0.0.0.0" to the command, so it binds to ALL network ports. ssh -L 0.0.0.0:X:destination:Y firewall ------------------------------------------------------------------------------- Using SSH proxy 'hold_command' With the above socks proxy, or port forwarding I usally like to have the ssh command run a 'holding program on the remote server. This command holds the port, to ensure it does not unexpectantally close. One command I use is... exec xlogo -name proxy -g 20x20-5+5 -fg red -bg navy \ -xrm 'proxy*baseTranslations: #override : quit()' I also sometimes use the color reversal, to denote the reverse direction... exec xlogo -name proxy -g 20x20-30+5 -fg blue -bg firebrick \ -xrm 'proxy*baseTranslations: #override : quit()' The 'xlogo' program is an X windows command that should exist on any machine with X windows capability (all UNIX machines). This means the command will automatically exit and die, closing the remote connections, when you log out of your machine. The special 'resource option' or -xrm is designed to let you close the connection by just pressing the mouse button on that small window. ------------------------------------------------------------------------------ SSH to one machine via a intermedite firewall host Add the following to your local ".ssh/config" host host1 host2 ProxyCommand ssh -qax firewall nc %h 22 You of cause need to be able to login to the firewall host and access the other machine from that machine. Note port 22 is the SSH server port, so the above forwards the connection via the firewall host to the destination hosts SSH port. EG: to connect to either "host1" or "host2" use the command given to go via a firewall host. The "nc" is the netcat command, which will not understand the other features, which the "-qax" argument will turnoff. Simularly the following will always open a forwarded port whenever a connection is made to a particular host... host firewall LocalForward 8080 webserver:80 EG: connect the port localhost:8080 to webserver:80 via the sshd on firewall ------------------------------------------------------------------------------- Socks Proxy via a firewall host. ssh -X -n -o BatchMode=yes -D 8080 firewall "cmd" & The command is some command to hold the connection open, when it ends the socks connection will also end. A good command is... exec xlogo -name proxy -g 20x20-5+5 -fg firebrick -bg navy \ -xrm 'proxy*baseTranslations: #override : quit()' This runs a small Xlogo that will just quit when the mouse button is pressed, or your X terminal session ends, thus closing the connection automatically. You can now point your web cliient and other network utilities to port 8080 on the local machine to socks connect via your firewall host to anywhere. For example... curl -v --socks5 localhost:8080 -m 30 -L http://www.aol.com.au/ | wc Unfortunatally you can not set environemnt variables to define a default socks proxy server (see next). You must tell each application what it is. ------------------------------------------------------------------------------- Web Proxy via firewall and another open web proxy server (old method) If you can find a open web proxy you have access to say proxy_ip:3128 This you can do this... ssh -X -n -o BatchMode=yes -L 4444:proxy_ip:3128 firewall "cmd" Where the "cmd" is a connection holder as per the socks proxy above. curl --proxy localhost:4444 -m 30 http://www.aol.com.au/ | wc You can no define environment variables like... # for lynx HTTP_PROXY = "http://localhost:4444/" NO_PROXY = ".list.of.local,.domains,.not.to.proxy" # for curl http_proxy = "$HTTP_PROXY" no_proxy = "$NO_PROXY" and it test with... curl -m 30 http://www.aol.com.au/ | wc and/or set the proxy setting of your web browser, and browse/download This is harder to setup (and find an open proxy on the web) but has the advantage that only connections from the firewall is to that web proxy. This makes it much more difficult for system adminastrators of the firewall to figure out what sites you are looking at and downloading from. ------------------------------------------------------------------------------- SSH Bit Torrent via a public Host Bit torrent needs an outgoing Socks Proxy, but also a Incomming remote port. The SSH daemon on remote machine must allow TcpForwarding and GatewayPorts. ssh -X -n -o BatchMode=yes -D 4001 \ -R 0.0.0.0:13481:localhost:13481 \ $remote_server "$hold_command" & This lets azurus use 13481 as its incomming port and 4001 on the localhost as the socks v5 proxy port. Configure Azureus... In Configuraton Wizard set Advanced options Under Preferences (Options) -> Connection: Set Incoming TCP listen port to 13481 Under Preferences (Options) -> Connection -> Proxy Options Check: Enable proxying of tracker communications Check: I have a SOCKS proxy Set: Host to 127.0.0.1 Set: Port to 4001 Check: Enable proxying of peer communications Check: Inform tracker of limitation Set: SOCKS version to V5 Check: Use same proxy settings for tracker and peer communications proxy Under Preferences (Options) -> Transfer: Check: Allow multiple connections from the same IP Now restart Azureus ------------------------------------------------------------------------------- SSH to a Dynamic (roaming) IP Address. If the machine you are trying to ssh to changes IP address, the following options allow you to select the right host key seperately to the actual address you attempt to SSH to. ssh -o CheckIP=no -o StrictHostKeyChecking=no -o HostKeyAlias={machine_name} {Current_IP_of_machine} This is usfull if you want to SSH back to a machine, which dialed onto the network via a PPP modem or dynamic ADSL connection. Eg ssh back to where you logged in using info in "$SSH_CLIENT" or "$SSH_CONNECTION" environment variable. ------------------------------------------------------------------------------- SSH security notes and ideas. Use a white list of acceptable IP's The problem is that you can't login from a random terminal when you need to. You may also have too many users to control access in this way. Only allow public key access. No passwords allowed, period. For random remote logins have putty and your private ssh key on a USB stick. NB: using the private key of public machines may not be a very good idea. Spot and deny SSH dictionary attacks... "denyHosts" either with otu without access to the central 'list' server. Adds 'deny' lines to the '/etc/hosts.deny" file when it sees an attack in the /var/log/secure file. A script to do the same thing locally is simple too, so you can DIY it. "sshdfilter", runs sshd with a -e filter to add iptable denys in real time rather than after the fact, often before a password has even been requested. It is highly configurable, and removed old entries according to various rules. However it is not avaialble as a yum package (yet) http://www.csc.liv.ac.uk/~greg/sshdfilter/ "sshd_sentry" (may not be released), after five failed attempts the IP address is blocked for 24 hours. The problem is it leaves you vulnerable to a DoS attack from competitors, not just SSH ports but for web bots access for google and yahoo search engines too. Limit logins to specific usernames. Dictionary attackers will give up as they don't really know your allowed user list. Change the sshd port on the extrnal routine... EG port forward 7xxx on the router --> 22 on your internal machine Note do not use port 2222. Everyone uses that and script kiddies will catch on to this, and scan for that port too. Not at time of writing though. One Time, or limited time Passwords. Do you have an SMS-enabled cell phone? For an operating systems class project this spring I wrote a simple PAM module what would look up the user's cell phone number then send an eight-digit random number to the user's cell phone, which the user has to type in at the login prompt. I used this module to secure the outward-facing sshd (on port 7xxx), blocking port 22 at the firewall so I could continue to ssh around my home network without spending $0.15 every time I rebooted my laptop. As long as your phone has a signal, you have effective token-based authentication. -------------------------------------------------------------------------------