Table of Contents

DESCRIPTION

Build a minimal serial console server. The goals are:

ALTERNATIVES

INSTALLATION

Dependencies

Compile

apt

apt install daemontools

Services

Create the service directory structure for daemontools:

service/
├── consolebot
│   └── run
├── console@host1
│   ├── log
│   │   └── run
│   └── run
├── console@host2
│   ├── log
│   │   └── run
│   └── run
└── xmpp
    └── run

Each serial console runs as a daemontools managed Unix process.

svscan /home/console/service
  ├─supervise console@host1
  │   └─unixexec /tmp/sredird/console@host1 hexlog none sredird -t 900 5 ...
  ├─supervise log
  │   └─tscat -o 3 console@host1
  ├─supervise console@host2
  │   └─unixexec /tmp/sredird/console@host2 hexlog none sredird -t 900 5...
  ├─supervise log
  │   └─tscat -o 3 console@host2
  ├─supervise xmpp
  │   └─xmppipe -o [email protected]
  └─supervise consolebot
      └─run ./run

console@host/run

#!/bin/bash

umask 077

mkdir -p /tmp/sredird

exec 2>&1
exec unixexec /tmp/sredird/console@getpid \
  hexlog none \
  sredird -t 900 5 /dev/console@getpid

console@host/log/run

#!/bin/bash

set -o errexit
set -o nounset
set -o pipefail

if [ ! -p "/tmp/sredird/monitor/stdin" ] || [ ! -p "/tmp/sredird/monitor/stdout" ]; then
  exit 1
fi
SERVICE="$(basename $(dirname $PWD))"
exec >/tmp/sredird/monitor/stdin
exec tscat -o 3 "$SERVICE"

xmpp/run

#!/bin/bash

set -o errexit
set -o nounset
set -o pipefail

shopt -s nullglob

umask 077

export XMPPIPE_PASSWORD="password"
export XMPPIPE_USERNAME="[email protected]"

TMPDIR="/tmp/sredird/monitor"
mkdir -p "$TMPDIR"

in="$TMPDIR/stdin"
out="$TMPDIR/stdout"

mkfifo "$in" 2>/dev/null || true
mkfifo "$out" 2>/dev/null || true

exec <"$in"
exec >"$out"
exec xmppipe -o [email protected]

consolebot/run

#!/bin/bash

set -o errexit
set -o nounset
set -o pipefail

shopt -s nullglob

umask 077

export SERVICE="$HOME/service"

TMPDIR="/tmp/sredird/monitor"

in="$TMPDIR/stdin"
out="$TMPDIR/stdout"

if [ ! -p "$in" ] || [ ! -p "$out" ]; then
  exit 0
fi

exec <"$out"
exec >"$in"

decode() {
  printf '%b' "${1//%/\\x}"
}

CODE='```'

export DEBUG=0
while IFS=: read stanza type from to body; do
  case "$stanza" in
    m) ;;
    *) continue ;;
  esac

  USER="$(decode "${from#*/}")"
  MSG="$(decode "$body")"

  case $MSG in
    h) ;&
    help)
      cat <<EOF
_Usage_

i *console* : display console session information

m *console* : monitor console session

status : display status of all consoles

t : terminate all consoles
t *console* : terminate console

EOF
      ;;
    t)
      lsof -t /dev/console@* | xargs --no-run-if-empty kill
      ;;

    't '[a-z]*)
      DEV="${MSG##* }"
      if [ ! -S "/tmp/sredird/console@${DEV}" ]; then
        echo "Invalid console: $DEV"
        continue
      fi
      lsof -t "/dev/console@${DEV}" | xargs --no-run-if-empty kill
      ;;
    'm '[a-z]*)
      DEV="${MSG##* }"
      if [ ! -S "/tmp/sredird/console@${DEV}" ]; then
        echo "Invalid console: ${DEV}"
        continue
      fi
      lsof -t "/dev/console@${DEV}" |
        xargs --no-run-if-empty xargs ps -o ppid= |
        xargs --no-run-if-empty kill -USR2
      ;;

    status)
      cat <<EOF

**Services**

$CODE
$(cd $SERVICE && svstat console@*)
$CODE

EOF
      ;&
    i) ;&
    I)
      cat <<'EOF'

**Consoles**

EOF
      for c in /dev/console@*; do
        cat <<EOF

*$c*

$CODE
$(lsof "$c" || echo "no user")
$CODE

EOF
      done
      ;;

    'I '[a-z]*) ;&
    'i '[0-9]*)
      DEV="${MSG##* }"
      if [ ! -S "/tmp/sredird/console@${DEV}" ]; then
        echo "Invalid console: ${DEV}"
        continue
      fi
      cat <<EOF

$CODE
$(lsof "/dev/console@${DEV}")
$CODE

EOF
      ;;
    exit)
      echo "exiting ..."
      exit 0
      ;;
    *)
      if [[ $MSG =~ ^[[:space:]]*$ ]]; then
          continue
      fi
      echo "Unknown command: $MSG" ;;
  esac
done

Building picocom

Patch the Makefile to enable RFC2217 support:

git clone https://github.com/npat-efault/picocom.git
git checkout -t origin/rfc2217
patch -p1 < Makefile.patch
make

Makefile.patch

diff --git a/Makefile b/Makefile
index 75f3fdb..234386d 100644
--- a/Makefile
+++ b/Makefile
@@ -46,9 +46,9 @@ linenoise-1.0/linenoise.o : linenoise-1.0/linenoise.c linenoise-1.0/linenoise.h
 #CPPFLAGS += -DNO_CUSTOM_BAUD

 ## Comment these in to enable RFC2217 support
-#CPPFLAGS += -DUSE_RFC2217
-#OBJS += tn2217.o
-#tn2217.o : tn2217.c tn2217.h tncomport.h fdio.h termint.h term.h
+CPPFLAGS += -DUSE_RFC2217
+OBJS += tn2217.o
+tn2217.o : tn2217.c tn2217.h tncomport.h fdio.h termint.h term.h

 ## Comment this IN to remove help strings (saves ~ 4-6 Kb).
 #CPPFLAGS += -DNO_HELP

Access

ssh

Host consoleserver
    RequestTTY no
    ExitOnForwardFailure yes

    # /dev/console@host1
    LocalForward 127.123.1.1:10023 /tmp/sredird/console@host1
    # /dev/console@host2
    LocalForward 127.123.2.1:10023 /tmp/sredird/console@host2
ssh -fNT consoleserver

Aliases

alias c-host1="picocom --telnet --baud 38400 127.123.1.1,10023"
alias c-host2="picocom --telnet --baud 38400 127.123.2.1,10023"

(markdown)