summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/Makefile43
-rw-r--r--services/README.md30
-rw-r--r--services/authorized_keys7
-rwxr-xr-xservices/bin/services40
-rwxr-xr-xservices/bin/show-services31
-rwxr-xr-xservices/bin/update-services-pubkeys3
-rw-r--r--services/checkers.py25
-rw-r--r--services/etc/conf.d/krebs-services-test-server3
-rw-r--r--services/etc/services/bootstrap13
-rw-r--r--services/etc/systemd/system/krebs-services-test-server.service14
-rw-r--r--services/services.txt7
-rwxr-xr-xservices/test-server.py113
12 files changed, 329 insertions, 0 deletions
diff --git a/services/Makefile b/services/Makefile
new file mode 100644
index 00000000..c537b50d
--- /dev/null
+++ b/services/Makefile
@@ -0,0 +1,43 @@
+help:;@cat Makefile
+export authorized_keys_file := authorized_keys
+export debug_log := true
+export services_file := services.txt
+export host_key_file := test.key
+export services_home := /opt/services
+
+.PHONY: authorized_keys
+
+
+service-user: $(services_home)/services.txt ssh_authorized_keys
+ @echo 'also make sure that the user is created: make create-service-user'
+
+create-service-user:
+ mkdir -p $(services_home)
+ rmdir $(services_home)
+ useradd -m -r -l -f -1 -d $(services_home) services
+
+ssh_authorized_keys: $(services_home)/.ssh/authorized_keys
+
+$(services_home)/.ssh:
+ mkdir $@
+ chown services:services $@
+
+$(services_home)/.ssh/authorized_keys: $(services_home)/.ssh $(authorized_keys_file)
+ cp $(authorized_keys_file) $(services_home)/.ssh/authorized_keys
+ @echo "restricting authorized_keys..."
+ @sed -i 's#^#command="/bin/cat $(services_home)/services.txt",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty #' $(services_home)/.ssh/authorized_keys
+ chown services:services $(authorized_keys_file)
+
+$(services_home)/services.txt:
+ @echo 'make sure to configure the services correctly in $(services_home)/services.txt'
+ cp $(services_file) $(services_home)/services.txt
+
+
+test-client:
+ ssh localhost -p 1337 2>/dev/null
+
+test-server:
+ ./test-server.py
+
+$(host_key_file):
+ ssh-keygen -t rsa -P '' -f $@
diff --git a/services/README.md b/services/README.md
new file mode 100644
index 00000000..1fc2bfe3
--- /dev/null
+++ b/services/README.md
@@ -0,0 +1,30 @@
+# //services
+
+## install service user
+
+ make create-service-user service-user
+ $EDITOR /opt/services/services.txt
+
+## install and run test-server.py as systemd service
+
+### install dependencies
+
+ pacman -S python2-pyasn1 twisted
+
+### install systemd service and configuration
+
+ cp /krebs/services/etc/systemd/system/krebs-services-test-server.service \
+ /etc/systemd/system/
+ cp /krebs/services/etc/conf.d/krebs-services-test-server \
+ /etc/conf.d/
+
+### create services user and populate it's home
+
+ useradd -m -r -l -f -1 -d /opt/services -k /var/empty services
+ sudo -u services ssh-keygen -t rsa -P '' -f /opt/services/test.key
+ $EDITOR /opt/services/services.txt
+
+### run now and every reboot
+
+ systemctl start krebs-services-test-server
+ systemctl enable krebs-services-test-server
diff --git a/services/authorized_keys b/services/authorized_keys
new file mode 100644
index 00000000..03774041
--- /dev/null
+++ b/services/authorized_keys
@@ -0,0 +1,7 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7YrLdnXDRU2XEdZDu1BmgiT0Vaxplf3bfvSm+5o3g4AcR2yCv7h2D633c9uA0gq52EJ3V5m8B1ZcxqA0zqDptKwx+ZTMUGDls7StH5xpJyk9j5gf8DzyDLQPQG2IYszCH+8esKjo3BOFxfey8NaX+k6gvQsG3lyV0PjLvvIy4gDuMn6dPZfVAlwNYFOUNgwpku3W3A0d+UFyVjt3/sgZxM+8C3y6QE1gwT5/NfBbHM5vaEqjHcVq1ui+7a4iOXFGKkZDcd7EX6cQZSbCzZL7sZ0OmB1WpAsDCvIXfzX1YfNA0sso7ldSF6ZUGNgwEk1LootnQlCK/dfbM+i62SZ+1 tv@iiso
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCv9TTt4FkzT3jlQ0VS2tX/GpQO9Ef0wIQ+g96foe4qSniBwR667T1gIhURrod/p7N9oQcWRrNohjgmSBZRYA0kW6ZyqYJkLvRv54nXv6j/8Xq2nG/KVfDqL0kp8if+JGeFlQElpWJiAbGifYkopFy69QiLYU2ndR7aPbx+5qm/dcwPJ7K+n6dyePynCZadtcabm3PuBFUxGLdT9ImDXMOPfXxPMlN/3eb78byuEuHnhCIvIGLMBGx+8QTXvu7kHpZObvkbsF1xjVs9fDpwVLjh7GWdwf3BZ/agFlI24ffyqCPFnuaxUVyfUZeqf4twRsIZkTTB47lHDhYiVkyGe8gd root@pigstarter.de
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCl3RTOHd5DLiVeUbUr/GSiKoRWknXQnbkIf+uNiFO+XxiqZVojPlumQUVhasY8UzDzj9tSDruUKXpjut50FhIO5UFAgsBeMJyoZbgY/+R+QKU00Q19+IiUtxeFol/9dCO+F4o937MC0OpAC10LbOXN/9SYIXueYk3pJxIycXwUqhYmyEqtDdVh9Rx32LBVqlBoXRHpNGPLiswV2qNe0b5p919IGcslzf1XoUzfE3a3yjk/XbWh/59xnl4V7Oe7+iQheFxOT6rFA30WYwEygs5As//ZYtxvnn0gA02gOnXJsNjOW9irlxOUeP7IOU6Ye3WRKFRR0+7PS+w8IJLag2xb makefu@pornocauster
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7df1RfMGNHPJe0iF6rD9DBs/4VujN6nNr7RbRCFk7HF/JzLXSn9Vcwk+3JefP4/d/bUo0h03rhQaRohDhBScrJidj2YacF6gmZOuTf3AMWprdz9D/1dDkN/ytwzGhADhqbHEWeomIllsa8Up4PvEeDcIHJGzYvuc0BbGqRk0XgxwqIrLAhdpTfEKaTbt7IzmUqEofxThTZ/4k020PKn2WDBWKQYGZJ9Ba2WzlKUXWx842ncW29oxC2faRz4M3eMPy0JMpBLkK9U3dccE75dgT/89/4ofVjM7+J3FOP3dgXzrtk+A5aN5a/veJUViQ9xdGxXvoa++iCr5q/BVRv0Bb sammy@muhbaasu.de
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDOIRWLC4ESCDxjyoJUqaUNC8ZDiE4UICZk3cbDptdtendTQvjSXz0RW6MWhJ+F6wWZntL1EibKn8djax1tzgcvNASCUEtGey/850IzBIrETs+WQDRjV2QqBKWxVaQPIFjw2V3vFSKKNxq01qznVBY510DIf4+0WR8b1ZPD/XbuyQLGYM3N7dP4JQSnnNAgtyutBKdomWfT18hW1lLjkP8h1IOiC03HxXTYX+nMUiLDff3D5GT5u3Ke2+VigXjz4Ue8rVsOg/zgqrwEAfx8o1q83uSB23oqUqWkqlxOC/4QY5kpdNqW/Iz89zHibp5ZceHd2ZSoGefv7UZM0lRIDHjJ retiolum@ire
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC3+2vSwiJoIpHpnkw4SslPrlR6/z43nZ7s1tGXkkNnVDB2uzxMaISNRjSk0GgXpDx4hLEi6074hSvv5JWbUuMyKr9n6GVVeYNCjsiPcRkL3d7zDwFwqyndhVeWgmpuylYx4XKIbTvpBVyG3CRT1+D4apVUgiDa9lVfjBk7/ESxBzt0dXtlJEzQBBoCo0C8jeeIpvZKbq1zeM9wvLsgFaT7fsSxrg5BEb/tQl6pbkykWFXbzzd91liEQaSqai7Ux2355ZXGANQBCTglKhdTcir0RuHNtQGrZHBxL9qVfJjJJNZg1b6UAhDanqE/HyOI3sp6LGBvpW5afLKOdj9ppQQN retiolum@nomic
+ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAp83zynhIueJJsWlSEykVSBrrgBFKq38+vT8bRfa+csqyjZBl2SQFuCPo+Qbh49mwchpZRshBa9jQEIGqmXxv/PYdfBFQuOFgyUq9ZcTZUXqeynicg/SyOYFW86iiqYralIAkuGPfQ4howLPVyjTZtWeEeeEttom6p6LMY5Aumjz2em0FG0n9rRFY2fBzrdYAgk9C0N6ojCs/Gzknk9SGntA96MDqHJ1HXWFMfmwOLCnxtE5TY30MqSmkrJb7Fsejwjoqoe9Y/mCaR0LpG2cStC1+37GbHJNH0caCMaQCX8qdfgMVbWTVeFWtV6aWOaRgwLrPDYn4cHWQJqTfhtPrNQ== death@uriel
diff --git a/services/bin/services b/services/bin/services
new file mode 100755
index 00000000..aa65e81e
--- /dev/null
+++ b/services/bin/services
@@ -0,0 +1,40 @@
+#! /bin/sh
+# usage: services [user@]hostname[:port]
+# environment:
+# services_identity_file path to ssh(1) identity_file
+set -euf
+
+user=services
+hostname=${1-localhost}
+port=1337
+
+options="${options+$options }-o ControlMaster=no"
+
+if test -n "${services_identity_file-}"; then
+ options="${options+$options }-i $services_identity_file"
+fi
+
+if echo $hostname | grep -q @; then
+ user=`echo $hostname | cut -d@ -f1`
+ hostname=`echo $hostname | cut -d@ -f2`
+fi
+if echo $hostname | grep -q :; then
+ port=`echo $hostname | cut -d: -f2`
+ hostname=`echo $hostname | cut -d: -f1`
+fi
+
+exec 3>&1
+{
+ set +e
+ ssh -T $options $user@$hostname -p $port
+ echo "# Exit:$?" >&2
+} 2>&1 1>&3 | {
+ err="`cat`"
+ code=`echo "$err" | sed -n 's/^# Exit:\([0-9]\+\)/\1/p'`
+ echo "$err" | sed '
+ /^Connection to '$hostname' closed/d
+ /^Shared connection to '$hostname' closed/d
+ /^# Exit:/d
+ ' >&2
+ exit $code
+}
diff --git a/services/bin/show-services b/services/bin/show-services
new file mode 100755
index 00000000..e94eb7c8
--- /dev/null
+++ b/services/bin/show-services
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+set -euf
+cd $(dirname $(readlink -f $0))
+usage(){
+ cat <<EOF
+usage: $0 [pubkey-file] [bootstrap-file]
+ if pubkey-file is "" it will be skipped.
+
+ e.g.:
+ $0 "" ../path/to/other/bootstrap
+EOF
+
+}
+pubfile=${1:-}
+bootfile=${2:-../etc/services/bootstrap}
+
+for i in `cat $bootfile`; do
+ # retard uriparsing but good enough for our use case
+ netloc=${i##*//}
+ host=${netloc%%:*}
+ port=${netloc##*:}
+ [ "$port" == "$host" ] && port=1337
+ echo $netloc
+ pubarg="${pubfile:+-i $pubfile}"
+ printf ""
+ ssh ${pubarg} "services@$host" -p "$port" \
+ -o PasswordAuthentication=no 2>/dev/null||:
+ printf ""
+done
+
diff --git a/services/bin/update-services-pubkeys b/services/bin/update-services-pubkeys
new file mode 100755
index 00000000..9936c402
--- /dev/null
+++ b/services/bin/update-services-pubkeys
@@ -0,0 +1,3 @@
+#!/bin/sh
+KREBS_ROOT="${KREBS_ROOT:-/krebs}"
+ssh $1 -t "cd ${KREBS_ROOT};git pull origin master;sudo -u services make -C $KREBS_ROOT/services ssh_authorized_keys"
diff --git a/services/checkers.py b/services/checkers.py
new file mode 100644
index 00000000..dbfe1323
--- /dev/null
+++ b/services/checkers.py
@@ -0,0 +1,25 @@
+
+import base64, binascii
+from twisted.python.filepath import FilePath
+from twisted.conch.checkers import SSHPublicKeyDatabase
+
+
+class PublicKeyChecker(SSHPublicKeyDatabase):
+
+ def __init__(self, filename):
+ self.filepath = FilePath(filename)
+
+ def getAuthorizedKeysFiles(self, credentials):
+ return [self.filepath]
+
+ def checkKey(self, credentials):
+ for line in self.filepath.open():
+ parts = line.split()
+ if len(parts) < 2:
+ continue
+ try:
+ if base64.decodestring(parts[1]) == credentials.blob:
+ return True
+ except binascii.Error:
+ continue
+ return False
diff --git a/services/etc/conf.d/krebs-services-test-server b/services/etc/conf.d/krebs-services-test-server
new file mode 100644
index 00000000..243054f4
--- /dev/null
+++ b/services/etc/conf.d/krebs-services-test-server
@@ -0,0 +1,3 @@
+authorized_keys_file=/krebs/services/authorized_keys
+services_file=/opt/services/services.txt
+host_key_file=/opt/services/test.key
diff --git a/services/etc/services/bootstrap b/services/etc/services/bootstrap
new file mode 100644
index 00000000..7dd9976c
--- /dev/null
+++ b/services/etc/services/bootstrap
@@ -0,0 +1,13 @@
+services://destroy
+services://ire
+services://darth:22
+services://pigstarter:22
+services://incept:22
+services://rage:22
+services://devstar:22
+services://heidi:22
+services://geisha:22
+services://slowpoke:22
+services://omo:22
+services://pico:22
+services://cband:22
diff --git a/services/etc/systemd/system/krebs-services-test-server.service b/services/etc/systemd/system/krebs-services-test-server.service
new file mode 100644
index 00000000..99578cce
--- /dev/null
+++ b/services/etc/systemd/system/krebs-services-test-server.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=services: provider
+After=network.target
+
+[Service]
+EnvironmentFile=/etc/conf.d/krebs-services-test-server
+ExecStart=/krebs/services/test-server.py
+KillMode=process
+User=services
+Group=services
+Restart=no
+
+[Install]
+WantedBy=multi-user.target
diff --git a/services/services.txt b/services/services.txt
new file mode 100644
index 00000000..265e6d1c
--- /dev/null
+++ b/services/services.txt
@@ -0,0 +1,7 @@
+owner:
+type:
+mail:
+expires:
+location:
+services://{{hostname}}:22
+tinc://{{hostname}}
diff --git a/services/test-server.py b/services/test-server.py
new file mode 100755
index 00000000..176373cf
--- /dev/null
+++ b/services/test-server.py
@@ -0,0 +1,113 @@
+#! /usr/bin/env python2
+
+from os import environ as env
+
+authorized_keys_file = env.get('authorized_keys_file', '/dev/null')
+debug_log = env.get('debug_log', 'false')
+services_file = env.get('services_file', '/dev/null')
+host_key_file = env.get('host_key_file', '/dev/null')
+host_key_pub_file = host_key_file + '.pub'
+
+
+from checkers import PublicKeyChecker
+from twisted.conch.avatar import ConchUser
+from twisted.conch.ssh.connection import SSHConnection
+from twisted.conch.ssh.factory import SSHFactory
+from twisted.conch.ssh.keys import Key
+from twisted.conch.ssh.session import SSHSession, ISession, wrapProtocol
+from twisted.conch.ssh.userauth import SSHUserAuthServer
+from twisted.cred.error import UnauthorizedLogin
+from twisted.cred.portal import IRealm, Portal
+from twisted.internet.protocol import Protocol
+from twisted.internet.reactor import listenTCP, run
+from twisted.internet.error import ProcessTerminated
+from twisted.python.components import registerAdapter
+from twisted.python.failure import Failure
+from zope.interface import implements
+
+if debug_log == 'true':
+ from twisted.python.log import startLogging
+ from sys import stderr
+ startLogging(stderr)
+
+
+class MyRealm:
+ implements(IRealm)
+
+ def requestAvatar(self, avatarId, mind, *interfaces):
+ return interfaces[0], MyUser(), lambda: None
+
+
+class MyUser(ConchUser):
+ def __init__(self):
+ ConchUser.__init__(self)
+ self.channelLookup.update({ 'session': SSHSession })
+
+
+class MySession:
+
+ def __init__(self, avatar):
+ pass
+
+ def getPty(self, term, windowSize, attrs):
+ pass
+
+ def execCommand(self, proto, cmd):
+ raise Exception("no executing commands")
+
+ def openShell(self, trans):
+ ep = MyProtocol()
+ ep.makeConnection(trans)
+ trans.makeConnection(wrapProtocol(ep))
+
+ def eofReceived(self):
+ pass
+
+ def closed(self):
+ pass
+
+
+registerAdapter(MySession, MyUser, ISession)
+
+
+def slurpTextfile(filename):
+ file = open(filename, 'r')
+ try:
+ return file.read()
+ finally:
+ file.close()
+
+class MyProtocol(Protocol):
+ def connectionMade(self):
+ data = slurpTextfile(services_file).replace('\n', '\r\n')
+ self.transport.write(data)
+ self.transport.processEnded(Failure(ProcessTerminated(0, None, None)))
+ self.transport.loseConnection()
+
+ #def dataReceived(self, data):
+ # if data == '\r':
+ # data = '\r\n'
+ # elif data == '\x03': #^C
+ # self.transport.loseConnection()
+ # return
+ # self.transport.write(data)
+
+
+class MyFactory(SSHFactory):
+ privateKeys = {
+ 'ssh-rsa': Key.fromFile(filename=host_key_file)
+ }
+ publicKeys = {
+ 'ssh-rsa': Key.fromFile(filename=host_key_pub_file)
+ }
+ services = {
+ 'ssh-userauth': SSHUserAuthServer,
+ 'ssh-connection': SSHConnection
+ }
+
+if __name__ == '__main__':
+ portal = Portal(MyRealm())
+ portal.registerChecker(PublicKeyChecker(authorized_keys_file))
+ MyFactory.portal = portal
+ listenTCP(1337, MyFactory())
+ run()