Jun 122018
 

This posting is about using the command-line ssh tool for relatively securely copying stuff around, and logging into devices. Many of the tips contained within are things I have had to pry out of the manual page for my own use and these notes are a way of keeping the information around without relying on my brain.

#1: It Comes With Windows

If you are running the latest version of Windows 10, you get the command-line versions of ssh and scp without dropping into the Linux shell :-

Of course you have been able to install ssh clients for Windows for years or even decades, but having it available by default is a big win. Particularly for Windows machines you don’t tweak with your favourite applications.

#2: Public/Private Key Authentication

This the first part of increasing security by only permitting key authentication so that password brute forcing attacks become impossible. With the assistance of an ssh agent (not covered here) or a passphrase-less key pair (not advisable), it is no longer necessary to enter a password.

Of course getting into this sort of thing can be very confusing especially as most instructions tend to get into far too much detail on the cryptography involved. To keep it simple, I shall avoid going on about the cryptography, and concentrate on how to get it to work.

The most important thing to remember about key authentication is that there are two keys – the private key (which should be kept as secure as possible on the client machine) and the public key (which is copied to the devices you want to connect to).

So to get started, you first need to generate a key pair, which can be done with ssh-keygen; this has lots of options, but at this point you can ignore them. After you enter the command, you can simply hit return at all the prompts to generate a key pair :-

Generating public/private rsa key pair.
Enter file in which to save the key (/home/mike/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/mike/.ssh/id_rsa.
Your public key has been saved in /home/mike/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:REMOVED mike@Michelin
The key's randomart image is:
+---[RSA 2048]----+
|=*+o ..  .B*..=o |
|o+++.  . =+o. o+.|
|.BE.+   + .  =  .|
|o+=& . . .    o  |
|. o +   S    .   |
|     .           |
|    SS           |
|              .  |
|     --          |
+----[SHA256]-----+

Of course this is not ideal because there is no passphrase, but to get started with that’s fine. You can ignore most of this output (except for the first item in the following list) but just in case :-

  1. The key pair is saved in the files ~/.ssh/id_rsa (the private key) and ~/.ssh/id_rsa.pub (the public key). The permissions are usually generated properly, but just to be safe you may want to reset the permissions anyway: chmod 0400 ~/.ssh ~/.ssh/id_rsa; chmod u+x ~/.ssh
  2. The key fingerprint can be used to check that when you are connecting that the keys haven’t changed unexpectedly.
  3. Alternatively (and slightly more of a reasonable check) you can check the fingerprint using the “randoart”.

Of course on its own, it doesn’t do much good. You have to copy it into place onto the machine you wish to authenticate to :-

$ ssh username@server mkdir .ssh
$ cat ~/.ssh/id_rsa.pub | ssh username@server cat ">>" .ssh/authorized_keys

Note the quotes around the “>>”; these are significant because you do not want the local machine’s shell to interpret them – they need to be interpreted by the remote machine’s shell. Normally I would simply “scp” the file into place, but appending to a supposedly non-existent file is safer – just in case it does exist and does contain public keys that are currently in use.

There are a whole bunch of options to the command, but the two most important ones are :-

  1. The -t option which is used to specify the key type to generate (dsa, rsa, ecdsa, and ed25519). This is mostly unnecessary, but some older and limited devices do not understand certain key types. And as time goes on, more key types will be declared “insecure”. So you may sometimes find the need to generate more secure keys. The simplest (but not very efficient) process for dealing with such situations is to generate a key for each key type and try each one in turn.
  2. The -f option which is used to specify the output filenames – the private key is saved under the name ‘filename’ and the public key under the name ‘filename.pub’.

#3: SSH Configuration File and Usernames

There are a ton of things that can be done with the ssh configuration file, but for this section I’ll stick with setting the username used to login to specific hosts – not because this is the most interesting thing that can be done, although it is quite useful.

The configuration file can be found (if it has been created) at ~/.ssh/config (with a system-wide version at /etc/ssh/ssh_config). Within that file, you can set global preferences, or host specific preferences :-

Username fred

Host router
  Username admin
Host dns*
  Username fxb
Host ds-* web-*
  Username baileyf
Host *
  Username fred

The first line (Username fred) instructs ssh to use the username ‘fred’ when no username is specified – ssh 192.168.77.98 effectively becomes ssh fred@192.168.77.87.

If you specify the same username within a Host section, the specified username is used for any hosts that the specification following the Host word. In the first case (“Host router”) the username “admin” will be used for any host called “router” but not “router.some.domain”.

In the case of the second clause, a wildcard is used which is very useful for specifying a range of hosts – the example can match “dns01”, “dns01.some.domain”, or even “dns02”. In fact the first Host section is an example of what you should not do – put in a single hostname without a wildcard because it will only activate if the hostname is specified exactly as given. Put a wildcard in there, and it will work whether you use a single hostname or use the fully qualified domain name.

You can also have more than one host specification – as in the “ds-* web-*” list.

And lastly you can (if you choose) use the Host declaration to specify a set of default values – in much the same way that configuration settings in the global context specify default values. Use whatever method you choose.

#4: Cryptographic Incompatibility

I have commented elsewhere on this, but basically the ssh developers have chosen to disable weak encryption by default. Personally I would prefer that ssh throw up huge warnings about weak cryptography, but what is done is done.

If you need to connect to something with weak cryptography, there are three potential ‘fixes’ to allow connections. Each of these is a keyword to add to a specific host section, followed by a specification of what ‘algorithm’ to add.

In each case, a connection attempt will give an indication of what is wrong together with an indication of what algorithm to include :-

» ssh admin@${someswitch}
Unable to negotiate with ${ip} port 22: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1

In this case, we can see that it is the KexAlgorithms we need to adjust and the algorithm we need to add is “diffie-hellman-group1-sha1” :-

Host someswitch*
  KexAlgorithms +diffie-hellman-group1-sha1

This can be repeated for Ciphers and (rarely) MACs.

#5: X11 and Port Forwarding

Run X11 gooey programs over an ssh connection? Of course .. why not?

This can be enabled on a host-by-host basis (it is off by default because it can be insecure) using the configuration file :-

Host pica*
  ForwardX11 yes

This is just a special case of port forwarding where a network port is connected (via the ssh session) to a remote network port. Port forwarding can be very useful – for example to access an internal web site temporarily that isn’t (and probably shouldn’t be) exposed with a hole through the firewall.

Of course this can be done with a VPN, but ssh may be simpler :-

Host pica*
  LocalForward 8000 8000

When the connection is made, a local port is opened (tcp/8000) and connected to tcp/8000 on the machine you are logging into.
 

Jan 192011
 

This is probably of less interest than most of my blog postings about Cisco routers, as it concerns something less commonly configured in the way I have done it – specifically a WAN link with a single IPv4 address and NATting to that address. However writing up my notes here is convenient to me, so you’ll have to put up with it. It is also very definitely worth bearing in mind the disclaimer here.

Basic NAT

First of all the “outside” interface needs to be configured as such from the NAT point of view :-

router#configure terminal
router(config)#interface fastethernet 4
router(config-if)#ip nat outside

This marks the interface in a way that lets the router know how addresses need to be NATted. Of course it is also necessary to configure the “inside” interfaces too :-

router#configure terminal
router(config)#interface vlan 101
router(config-if)#ip nat inside

And repeat for each VLAN of course.

In most instructions you will see that it is normal to create a pool of addresses for use by NAT which is perfectly valid for a number of addresses to NAT to, and even when there is a single address. But there is an easier way … NAT to the address of the interface.

router#configure terminal
router(config)#ip nat inside source list 7 interface FasterEthernet4 overload

The next task is to specify an access list to match the addresses that need to be NATted.

router#configure terminal
router(config)#access-list 7 permit 10.0.0.0 /8

Port Forwarding or Static NAT (for Servers)


If you run your own servers you will need to arrange for incoming connections to certain tcp or udp ports to be ‘forwarded’ to a specified address. This is known in the domestic router scene as “port forwarding” which is as good a term for anything – given that the concept of NAT is fundamentally broken.

This is done quite simply by the following :-

router#configure terminal
router(config)#ip nat inside source static tcp 10.0.0.14 80 interface FastEthernet4 80

This of course says that there should be a static rule to map tcp/80 (http for the web) on the server with the address 10.0.0.14 to tcp/80 on the ‘outside’.

A Basic Firewall

Next task is to bring up the WAN connection to check it works ? Not at all; whilst it may be somewhat unhelpful to connect things up after having made multiple changes, it is important to have some kind of firewall running. If you happen to have the IOS firewall feature, there is little point in bothering with the ordinary ACL feature – it sucks in comparison.

But strangely it seems we do need a basic ACL in place to :-

  1. Allow server traffic into the network.
  2. Deny all other traffic.
  3. And to allow the inspect engine to extend the ACL to allow session specific rules.
router#configure terminal
router(config)#ip access-list extended AllowIn
router(config-ext-nacl)#permit tcp any any eq www
router(config-ext-nacl)#deny ip any any log DenyIn

The use of a named ACL here is to allow for greater self-documentation – it is easier to see what an ACL should be used for when it is named. This becomes more important the more ACLs are in use.

We then need to create a set of inspect rules to allow traffic out. This is a very open set of rules, and will dynamically create temporary rules to allow the inbound replies to the allowed outbound traffic. The ordering of this is very important as we need to most specific inspections first – so “inspect tcp”, etc should appear at the end.

router(config)#ip inspect name allow-out bittorrent
router(config)#ip inspect name allow-out ftp
router(config)#ip inspect name allow-out ftps
router(config)#ip inspect name allow-out gnutella
router(config)#ip inspect name allow-out h323
router(config)#ip inspect name allow-out http audit-trail on
router(config)#ip inspect name allow-out https audit-trail on
router(config)#ip inspect name allow-out icmp router-traffic
router(config)#ip inspect name allow-out tcp
router(config)#ip inspect name allow-out udp

The ‘router-traffic’ on the icmp rule is to allow the router to send ICMP traffic to the outside interface and for it to be inspected. For some strange reason, Cisco configured the default to not allow it – leading to any number of network administrators having a nasty panic attack. Perhaps Cisco have a nasty sense of humour?

Next, because it’s fun to see what people may be doing, we need to log whatever the inspection engine drops :-

router(config)#ip inspect log drop-pkt

Finally we apply the new rules to the WAN interface :-

router#(config)#interface fastethernet 4
router#(config-if)#ip access-group AllowIn in
router#(config-if)#ip inspect allow-out out
router#(config-if)#end

This just touches on the capabilities of firewalling with a Cisco and is well worth checking in greater depth. For instance, it is clearly possible to inspect incoming traffic as well as outgoing traffic, but if you do the obvious you end up with a non-working firewall

Bringing Up The WAN

Fortunately I am in the situation where my ADSL line is bridged to Ethernet using an ADSL ‘modem’ so that I merely have to configure the external WAN interface on my router with an external address, a netmask, etc. This is so trivial it seems strange to include it here, but …

router#configure terminal
router(config)#interface FastEthernet4
router(config-if)#ip address 192.168.1.1 255.255.248.0
router(config-if)#ip nat outside
router(config-if)#ip virtual-reassembly
router(config-if)#duplex auto
router(config-if)#speed auto
router(config-if)#end

Perhaps the only oddity there is the use of ‘ip virtual-reassembly’ which is essentially used to protect the router (and in effect the rest of the network) from fragmented packet attacks. And if you prefer to leave CDP enabled, you may also want to stop that on the external interface with “no cdp enable” as well.