diff options
Diffstat (limited to 'services')
| -rw-r--r-- | services/Makefile | 43 | ||||
| -rw-r--r-- | services/README.md | 30 | ||||
| -rw-r--r-- | services/authorized_keys | 7 | ||||
| -rwxr-xr-x | services/bin/services | 40 | ||||
| -rwxr-xr-x | services/bin/show-services | 31 | ||||
| -rwxr-xr-x | services/bin/update-services-pubkeys | 3 | ||||
| -rw-r--r-- | services/checkers.py | 25 | ||||
| -rw-r--r-- | services/etc/conf.d/krebs-services-test-server | 3 | ||||
| -rw-r--r-- | services/etc/services/bootstrap | 13 | ||||
| -rw-r--r-- | services/etc/systemd/system/krebs-services-test-server.service | 14 | ||||
| -rw-r--r-- | services/services.txt | 7 | ||||
| -rwxr-xr-x | services/test-server.py | 113 |
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 "[32m" + ssh ${pubarg} "services@$host" -p "$port" \ + -o PasswordAuthentication=no 2>/dev/null||: + printf "[0m" +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() |
