*************************** Raspberry Pi Console Server *************************** Out of band remote console access to devices can be incredibly useful as it continues to work no matter what configuration (or lack of configuration) is present on the device. Remote console access can easily be achieved, with some inexpensive hardware and a Raspberry Pi. .. image:: ../images/raspi_serial_server/pi_console_in_rack3.jpg :alt: Raspberry Pi Console server Hardware Requirements ===================== Option 1 - using single USB to Serial adapters ---------------------------------------------- .. image:: ../images/raspi_serial_server/pi_console_server_usb_to_serial.jpg :alt: USB to serial * Raspberry Pi Model B or B+ with 4GB SD card * USB Hub (Powered) * USB to Serial adapters (one for each console connection) * USB cable - A to Micro B (to power Pi) * Cisco console/rollover cables (one for each console connection) * Ethernet cable Option 2 - using single USB to multiple Serial adapters ------------------------------------------------------- .. image:: ../images/raspi_serial_server/usb-to-multi-serial.jpg :alt: USB to multi serial * Raspberry Pi Model B or B+ with 4GB SD card * USB to multiple Serial adapter * USB cable - A male to Micro B male * Power supply (1 Amp @ 5V or greater) * Cisco console/rollover cables (one for each console connection) * Ethernet cable Optional for 1 & 2 ------------------ * Rack-mount 1U case * Raspberry Pi case Deciding what hardware to use ============================= I decided on, and would recommend, option 1 for the following reasons: * USB to single serial cables are cheap, really cheap (approx £2 on eBay) vs approx £25 for a USB to 4 serial ports cable. * Including a USB powered hub in the design eliminates the need for a separate PSU as the Pi can be powered from the hub. * Having a USB hub allows greater flexibility to later add a multitude of USB devices to the Pi (Wifi dongles, Flash drives, USB to Ethernet adapters, etc.) Hardware Installation ===================== After some research I opted for the following hardware based on my requirements for at least 6 console connections: * 1 x Raspberry Pi model B (£25 from CPC Farnell) with 16GB SD card (£10 ebuyer) * 1 x 10 port Pro Signal PSG90593 2.5A PSU should be more than adequate (£20 from CPC Farnell) * 6 x generic USB to serial cables (circa £2 on eBay) * 1 x generic 1U rack box (eBay auction score, £5 delivered!) * USB A to Micro USB B cable (already had) * Ethernet cable (already had) Total cost comes in around £75 for the console server setup. Given the Pi is running Linux, additional services can be configured to get even more use from the hardware. The hardware installed in the 1U rack box. .. image:: ../images/raspi_serial_server/pi_console_1u.jpg :alt: Raspberry Pi Console server Blu-tack was used to hold the Pi and Hub in place allowing for easy alterations to be made later. Some basic cable management was done to neaten things up a little. The USB hubs up-link port is plugged to one of the Pi's USB ports and another of the hubs USB port provides power to the Pi. 4 free USB ports (1 on the Pi and 3 on the hub) are available for further expansion. Software Installation ===================== The following assumes Rasbian Linux is already installed on the Pi with SSH access. ser2net is a program that proxies TCP connections to serial ports on the Pi. ser2net is available in the default Rasbian repositories. Install ser2net: .. raw:: html
    pi@pi01 ~ $ sudo apt-get install ser2net
    Reading package lists... Done
    Building dependency tree       
    Reading state information... Done
    The following NEW packages will be installed:
      ser2net
    0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded.
    Need to get 0 B/51.9 kB of archives.
    After this operation, 89.1 kB of additional disk space will be used.
    Selecting previously unselected package ser2net.
    (Reading database ... 105492 files and directories currently installed.)
    Preparing to unpack .../ser2net_2.9.1-1_armhf.deb ...
    Unpacking ser2net (2.9.1-1) ...
    Processing triggers for man-db (2.7.0.2-5) ...
    Processing triggers for systemd (215-17+deb8u7) ...
    Setting up ser2net (2.9.1-1) ...
    
Now we need to determine to which lines our USB to serial adapters are connected (a mixture of USB to serial cables were used hence the different chip sets listed): .. raw:: html
    pi@pi01 ~ $ dmesg | grep ttyUSB
    [   14.448749] usb 1-1.3.5: ch341-uart converter now attached to ttyUSB0
    [   14.488864] usb 1-1.3.6: ch341-uart converter now attached to ttyUSB1
    [   14.521964] usb 1-1.3.7.2: ch341-uart converter now attached to ttyUSB2
    [   14.561924] usb 1-1.3.7.3: ch341-uart converter now attached to ttyUSB3
    [   14.598247] usb 1-1.3.7.4: ch341-uart converter now attached to ttyUSB4
    [   14.958674] usb 1-1.3.7.1: pl2303 converter now attached to ttyUSB5
    
ser2net could be configured to use the `/dev/ttyUSB#` device names however these are not stable and can change on each boot as they are assigned in the order the kernel discovers the USB deices. udev rules can be created to assign aliases to each USB serial adapter and ser2net can then be configured using these aliases to obtain a persistent configuration. Creating udev rules ------------------- Writing udev rules for the USB to serial adapters is a little tricky because they are connected to the Pi through a USB hub so they all get assigned the same serial number: .. raw:: html
    pi@pi01 ~ $ for i in {0..5}; do udevadm info -a -n /dev/ttyUSB$i | grep -i "KERNEL\|{Serial}"; echo -e "\n" ; done KERNEL=="ttyUSB0"
    ATTRS{serial}=="20980000.usb"


    KERNEL=="ttyUSB1"
    ATTRS{serial}=="20980000.usb"


    KERNEL=="ttyUSB2"
    ATTRS{serial}=="20980000.usb"


    KERNEL=="ttyUSB3"
    ATTRS{serial}=="20980000.usb"


    KERNEL=="ttyUSB4"
    ATTRS{serial}=="20980000.usb"


    KERNEL=="ttyUSB5"
    ATTRS{serial}=="20980000.usb"
    
The above bash "one-liner" looped through the 6 ttyUSB# devices and preformed an attribute walk using `udevadm`, results were filtered to show only the dev name assigned by the kernel and device serial number (hubs serial number). Fortunately the `KERNELS==` udev attribute appears to show which port of the USB hub each device is plugged into allowing udev rules to be written to identify each USB to serial adapter and assign a persistent alias to it (so long as the adapters remain plugged into the same ports on the hub). .. raw:: html
    pi@pi01 ~ $ for i in {0..5}; do udevadm info -a -n /dev/ttyUSB$i | grep -i "KERNEL==\|{Serial}"; echo -e "\n" ; done 
    KERNEL=="ttyUSB0"
    KERNELS=="ttyUSB0"
    KERNELS=="1-1.3.5:1.0"
    KERNELS=="1-1.3.5"
    KERNELS=="1-1.3"
    KERNELS=="1-1"
    KERNELS=="usb1"
    ATTRS{serial}=="20980000.usb"
    KERNELS=="20980000.usb"
    KERNELS=="soc"
    KERNELS=="platform"


    KERNEL=="ttyUSB1"
    KERNELS=="ttyUSB1"
    KERNELS=="1-1.3.6:1.0"
    KERNELS=="1-1.3.6"
    KERNELS=="1-1.3"
    KERNELS=="1-1"
    KERNELS=="usb1"
    ATTRS{serial}=="20980000.usb"
    KERNELS=="20980000.usb"
    KERNELS=="soc"
    KERNELS=="platform"


    KERNEL=="ttyUSB2"
    KERNELS=="ttyUSB2"
    KERNELS=="1-1.3.7.2:1.0"
    KERNELS=="1-1.3.7.2"
    KERNELS=="1-1.3.7"
    KERNELS=="1-1.3"
    KERNELS=="1-1"
    KERNELS=="usb1"
    ATTRS{serial}=="20980000.usb"
    KERNELS=="20980000.usb"
    KERNELS=="soc"
    KERNELS=="platform"


    KERNEL=="ttyUSB3"
    KERNELS=="ttyUSB3"
    KERNELS=="1-1.3.7.3:1.0"
    KERNELS=="1-1.3.7.3"
    KERNELS=="1-1.3.7"
    KERNELS=="1-1.3"
    KERNELS=="1-1"
    KERNELS=="usb1"
    ATTRS{serial}=="20980000.usb"
    KERNELS=="20980000.usb"
    KERNELS=="soc"
    KERNELS=="platform"


    KERNEL=="ttyUSB4"
    KERNELS=="ttyUSB4"
    KERNELS=="1-1.3.7.4:1.0"
    KERNELS=="1-1.3.7.4"
    KERNELS=="1-1.3.7"
    KERNELS=="1-1.3"
    KERNELS=="1-1"
    KERNELS=="usb1"
    ATTRS{serial}=="20980000.usb"
    KERNELS=="20980000.usb"
    KERNELS=="soc"
    KERNELS=="platform"


    KERNEL=="ttyUSB5"
    KERNELS=="ttyUSB5"
    KERNELS=="1-1.3.7.1:1.0"
    KERNELS=="1-1.3.7.1"
    KERNELS=="1-1.3.7"
    KERNELS=="1-1.3"
    KERNELS=="1-1"
    KERNELS=="usb1"
    ATTRS{serial}=="20980000.usb"
    KERNELS=="20980000.usb"
    KERNELS=="soc"
    KERNELS=="platform"
    
Create the following udev rules to assign aliases: .. raw:: html
    pi@pi01 ~ $ sudo nano /etc/udev/rules.d/99-user.rules
    SUBSYSTEM=="tty", KERNEL=="ttyUSB*", KERNELS=="1-1.3.7.1", SYMLINK+="Cisco_3850-1"
    SUBSYSTEM=="tty", KERNEL=="ttyUSB*", KERNELS=="1-1.3.7.2", SYMLINK+="Cisco_2851-1"
    SUBSYSTEM=="tty", KERNEL=="ttyUSB*", KERNELS=="1-1.3.7.3", SYMLINK+="Cisco_2851-2"
    SUBSYSTEM=="tty", KERNEL=="ttyUSB*", KERNELS=="1-1.3.7.4", SYMLINK+="Cisco_1841-1"
    SUBSYSTEM=="tty", KERNEL=="ttyUSB*", KERNELS=="1-1.3.5", SYMLINK+="Cisco_1841-2"
    SUBSYSTEM=="tty", KERNEL=="ttyUSB*", KERNELS=="1-1.3.6", SYMLINK+="Cisco_1841-3"
    
After rebooting the Pi check that the aliases are assigned correctly: .. raw:: html
    pi@pi01 ~ $ ls -al /dev/Cisco_*
    lrwxrwxrwx 1 root root 7 Apr 17 15:34 /dev/Cisco_1841-1 -> ttyUSB5
    lrwxrwxrwx 1 root root 7 Apr 17 15:34 /dev/Cisco_1841-2 -> ttyUSB0
    lrwxrwxrwx 1 root root 7 Apr 17 15:34 /dev/Cisco_1841-3 -> ttyUSB1
    lrwxrwxrwx 1 root root 7 Apr 17 15:34 /dev/Cisco_2851-1 -> ttyUSB3
    lrwxrwxrwx 1 root root 7 Apr 17 15:34 /dev/Cisco_2851-2 -> ttyUSB4
    lrwxrwxrwx 1 root root 7 Apr 17 15:34 /dev/Cisco_3850-1 -> ttyUSB2
    
Configure ser2net ----------------- The USB to serial adapters are now addressable under persistent device aliases, these aliases can be used in the ser2net configuration file: .. raw:: html
    pi@pi01 ~ $ sudo nano /etc/ser2net.conf
    
Add the following lines to create a distinct banner for each device and configure each console connection. Each serial port is configured with the standard Cisco settings: .. code-block:: text Bits per sec : 9600 Data bits : 8 Parity : none Stop bits : 1 Flow control : none .. code-block:: text :linenos: TRACEFILE:tr1:/var/log/ser2net/tr-\p-\Y-\M-\D-\H:\i:\s BANNER:banner_3850-1:\r\nser2net port \p device \d [\s] (Cisco 3850-1 PoE Switch)\r\n\r\n BANNER:banner_2851-1:\r\nser2net port \p device \d [\s] (Cisco 2851-1 ISR Router + eswitch module)\r\n\r\n BANNER:banner_2851-2:\r\nser2net port \p device \d [\s] (Cisco 2851-2 ISR Router + eswitch module)\r\n\r\n BANNER:banner_1841-1:\r\nser2net port \p device \d [\s] (Cisco 1841-1 Router)\r\n\r\n BANNER:banner_1841-2:\r\nser2net port \p device \d [\s] (Cisco 1841-2 Router)\r\n\r\n BANNER:banner_1841-3:\r\nser2net port \p device \d [\s] (Cisco 1841-3 Router)\r\n\r\n 5000:telnet:0:/dev/Cisco_3850-1:9600 8DATABITS NONE 1STOPBIT banner_3850-1 tr=tr1 timestamp 5001:telnet:0:/dev/Cisco_2851-1:9600 8DATABITS NONE 1STOPBIT banner_2851-1 tr=tr1 timestamp 5002:telnet:0:/dev/Cisco_2851-2:9600 8DATABITS NONE 1STOPBIT banner_2851-2 tr=tr1 timestamp 5003:telnet:0:/dev/Cisco_1841-1:9600 8DATABITS NONE 1STOPBIT banner_1841-1 tr=tr1 timestamp 5004:telnet:0:/dev/Cisco_1841-2:9600 8DATABITS NONE 1STOPBIT banner_1841-2 tr=tr1 timestamp 5005:telnet:0:/dev/Cisco_1841-3:9600 8DATABITS NONE 1STOPBIT banner_1841-3 tr=tr1 timestamp Line 1: Creates a template to use for logging commands typed in each console session locally on the Pi. Log files are saved to /var/log/ser2net/ under the file name "tr---