Skip to content

Instantly share code, notes, and snippets.

@Jc2k
Last active November 20, 2017 05:51
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jc2k/e48a679328bb3f507182fa1d5b82a582 to your computer and use it in GitHub Desktop.
Save Jc2k/e48a679328bb3f507182fa1d5b82a582 to your computer and use it in GitHub Desktop.
Installing cowrie with systemd on Ubuntu 16.04

This is a quick demo of using twisted enpoints with cowrie to be able to use systemd socket activation. This has been tested on a fresh install of Ubuntu 16.04.2:

Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-62-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

Last login: Tue May  2 23:47:09 2017

Before proceeding configure SSH to run on a different port.

If you are upgrading an existing cowrie box make sure:

  • You remove any iptables PREROUTING rules that you have added for cowrie (i.e. to redirect port 22 to 2222)
  • You have updated cowrie.cfg to use systemd endpoints exclusively
  • You have stopped any cowrie processes that are already running
  • If you already have a cowrie.service in /etc/systemd/system i suggest disabling it with sudo systemctl disable cowrie.service. We will be creating a cowrie.socket that starts cowrie.service on demand.

Some OS's have abstractions around systemd like the service command. Socket activation was not a use case they considered when designing those abstractions. I strongly suggest dropping down to the underlying systemctl command when working on this setup. There's not actually much difference, but it might help avoid some confusion.

We need the usual dependencies:

$ sudo apt install git python-pip libmpfr-dev libssl-dev libmpc-dev libffi-dev build-essential libpython-dev python2.7-minimal
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  binutils cpp cpp-5 dpkg-dev fakeroot g++ g++-5 gcc gcc-5 git-man libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl libasan2
  libatomic1 libc-dev-bin libc6 libc6-dev libcc1-0 libcilkrts5 libdpkg-perl liberror-perl libexpat1-dev libfakeroot libfile-fcntllock-perl libgcc-5-dev
  libgmp-dev libgmpxx4ldbl libgomp1 libisl15 libitm1 liblsan0 libmpc3 libmpfr4 libmpx0 libperl5.22 libpython-all-dev libpython-stdlib libpython2.7
  libpython2.7-dev libpython2.7-minimal libpython2.7-stdlib libquadmath0 libssl-doc libstdc++-5-dev libtsan0 libubsan0 linux-libc-dev make manpages-dev
  patch perl perl-modules-5.22 python python-all python-all-dev python-dev python-minimal python-pip-whl python-pkg-resources python-setuptools
  python-wheel python2.7 python2.7-dev rename xz-utils zlib1g-dev
Suggested packages:
  binutils-doc cpp-doc gcc-5-locales debian-keyring g++-multilib g++-5-multilib gcc-5-doc libstdc++6-5-dbg gcc-multilib autoconf automake libtool flex
  bison gdb gcc-doc gcc-5-multilib libgcc1-dbg libgomp1-dbg libitm1-dbg libatomic1-dbg libasan2-dbg liblsan0-dbg libtsan0-dbg libubsan0-dbg
  libcilkrts5-dbg libmpx0-dbg libquadmath0-dbg git-daemon-run | git-daemon-sysvinit git-doc git-el git-email git-gui gitk gitweb git-arch git-cvs
  git-mediawiki git-svn glibc-doc gmp-doc libgmp10-doc libmpfr-doc libstdc++-5-doc make-doc diffutils-doc perl-doc libterm-readline-gnu-perl
  | libterm-readline-perl-perl python-doc python-tk python-setuptools-doc python2.7-doc binfmt-support
The following NEW packages will be installed:
  binutils build-essential cpp cpp-5 dpkg-dev fakeroot g++ g++-5 gcc gcc-5 git git-man libalgorithm-diff-perl libalgorithm-diff-xs-perl
  libalgorithm-merge-perl libasan2 libatomic1 libc-dev-bin libc6-dev libcc1-0 libcilkrts5 libdpkg-perl liberror-perl libexpat1-dev libfakeroot libffi-dev
  libfile-fcntllock-perl libgcc-5-dev libgmp-dev libgmpxx4ldbl libgomp1 libisl15 libitm1 liblsan0 libmpc-dev libmpc3 libmpfr-dev libmpfr4 libmpx0
  libperl5.22 libpython-all-dev libpython-dev libpython-stdlib libpython2.7 libpython2.7-dev libpython2.7-minimal libpython2.7-stdlib libquadmath0
  libssl-dev libssl-doc libstdc++-5-dev libtsan0 libubsan0 linux-libc-dev make manpages-dev patch perl perl-modules-5.22 python python-all python-all-dev
  python-dev python-minimal python-pip python-pip-whl python-pkg-resources python-setuptools python-wheel python2.7 python2.7-dev python2.7-minimal rename
  xz-utils zlib1g-dev
The following packages will be upgraded:
  libc6
1 upgraded, 75 newly installed, 0 to remove and 46 not upgraded.
Need to get 89.3 MB of archives.
After this operation, 289 MB of additional disk space will be used.
Do you want to continue? [Y/n] 
<snip>
Processing triggers for libc-bin (2.23-0ubuntu5) ...

We'll have a dedicated cowrie user to run as:

$ sudo addgroup --gid 9001 cowrie
$ sudo adduser --home /home/cowrie --uid 9001 --ingroup cowrie --gecos "Cowrie" --disabled-password cowrie

Check out the cowrie source (as the cowrie user)

$ sudo su cowrie
cowrie@localhost $ git clone git://github.com/micheloosterhof/cowrie /home/cowrie/cowrie
Cloning into '/home/cowrie/cowrie'...
remote: Counting objects: 7819, done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 7819 (delta 6), reused 0 (delta 0), pack-reused 7796
Receiving objects: 100% (7819/7819), 6.53 MiB | 2.10 MiB/s, done.
Resolving deltas: 100% (5304/5304), done.
Checking connectivity... done.

Install the cowrie python deps. Here I'm installing them globally, thats a bit cheaty but it'll do for this walkthrough - which is more about the new systemd activation support than how to setup cowrie properly.

$ sudo pip install -r /home/cowrie/cowrie/requirements.txt 
Collecting twisted>=15.2.1 (from -r /home/cowrie/cowrie/requirements.txt (line 1))
  Downloading Twisted-17.1.0.tar.bz2 (3.0MB)
    100% |████████████████████████████████| 3.0MB 564kB/s 
<snip>
  Running setup.py install for tftpy ... done
Successfully installed Automat-0.5.0 appdirs-1.4.3 asn1crypto-0.22.0 attrs-16.3.0 cffi-1.10.0 configparser-3.5.0 constantly-15.1.0 cryptography-1.8.1 enum34-1.1.6 gmpy2-2.0.8 idna-2.5 incremental-16.10.1 ipaddress-1.0.18 packaging-16.8 pyasn1-0.2.3 pyasn1-modules-0.0.8 pycparser-2.17 pycrypto-2.6.1 pyopenssl-17.0.0 pyparsing-2.2.0 python-dateutil-2.6.0 service-identity-16.0.0 six-1.10.0 tftpy-0.6.2 twisted-17.1.0 zope.interface-4.4.0
You are using pip version 8.1.1, however version 9.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

Copy the cowrie.cfg.dist to /home/cowrie/cowrie/cowrie.cfg and edit it. The one below is the stock config, but i've changed listen_endpoints and enabled telnet.

$ sudo cp -a /home/cowrie/cowrie/cowrie.cfg.dist /home/cowrie/cowrie/cowrie.cfg
$ sudo -u cowrie vi /home/cowrie/cowrie/cowrie.cfg
$ cat /home/cowrie/cowrie/cowrie.cfg
[honeypot]
hostname = svr04
log_path = log
download_path = dl
data_path = data
contents_path = honeyfs
filesystem_file = data/fs.pickle
txtcmds_path = txtcmds
ttylog = true
auth_class = UserDB

[ssh]
enabled = true
rsa_public_key = etc/ssh_host_rsa_key.pub
rsa_private_key = etc/ssh_host_rsa_key
dsa_public_key = etc/ssh_host_dsa_key.pub
dsa_private_key = etc/ssh_host_dsa_key
version = SSH-2.0-OpenSSH_6.0p1 Debian-4+deb7u2
listen_endpoints = systemd:domain=INET:index=0
sftp_enabled = true
forwarding = true
forward_redirect = false

[telnet]
enabled = true
listen_endpoints = systemd:domain=INET:index=1

[output_jsonlog]
logfile = log/cowrie.json

We add a systemd unit that will listen on some ports for us:

$ cat /etc/systemd/system/cowrie.socket 
[Unit]
Description=Cowrie SSH/Telnet sockets

[Socket]
ListenStream=0.0.0.0:22
ListenStream=0.0.0.0:23

[Install]
WantedBy=sockets.target

Here we are only listening on 2 ports but I have tested with with more than 5.

Systemd will listen on these interface/ports for us and send file descriptors for them to our service unit. That service unit will refer to them by index in order. In cowrie.cfg we'll use descriptors like systemd:domain=INET:index-X to reference these ports. It's important to grok the connection. So:

  • systemd:domain=INET:index=0 corresponds to ListenStream=0.0.0.0:22
  • systemd:domain=INET:index=1 corresponds to ListenStream=0.0.0.0:23

This means that if you try to group your streams by SSH and by telnet and then add a new ListenStream in the middle of the existing ones you must remember to update cowrie.cfg and shuffle them all along!!!

Now we add a systemd unit that accept connections from those ports:

$ cat /etc/systemd/system/cowrie.service 
[Unit]
Description=Cowrie SSH and Telnet Honeypot
After=network.target
Requires=cowrie.socket

[Service]
Type=simple
User=cowrie
Group=cowrie
Environment=PYTHONPATH=/home/cowrie/cowrie:/usr/lib/python2.7:/usr/lib/python2.7/plat-x86_64-linux-gnu:/usr/lib/python2.7/lib-tk:/usr/lib/python2.7/lib-old:/usr/lib/python2.7/lib-dynload:/usr/local/lib/python2.7/dist-packages:/usr/lib/python2.7/dist-packages
Environment=PYTHONUNBUFFERED=true
ExecStart=/usr/local/bin/twistd -n -l - --umask 0077 --pidfile= cowrie
WorkingDirectory=/home/cowrie/cowrie/
NonBlocking=yes
Restart=always
TimeoutSec=300

[Install]
WantedBy=multi-user.target

We don't use forking, and thus we don't use cowrie start or pid files. This just simplifies the number of moving pieces - its complicated enough with having the sockets opened for us by another process. cowrie start just sets up the environment (i.e. PYTHONPATH) and chains on to the twistd process. We can do everything it does up front in our systemd unit.

The twistd parameters we care about in particular are:

  • We don't fork (-n). Twistd 'runs in the foreground' (systemd handles running it as a service for us)
  • We send the twistd logs to stdout (-l -) and let systemd manage logging. You can see the ouput with journalctl -u cowrie and tail with journalctl -u cowrie -f.
  • We turn off pid files (--pidfile=). They aren't needed when systemd is supervising cowrie. There are less moving pieces if we turn them off.

We set PYTHONUNBUFFERED because python will buffer stdio usage normally, and that can add hide error messages from you when you are trying to debug things.

We set PYTHONPATH explicitly. We need /home/cowrie/cowrie to be on it so twisted can find twisted/plugins/cowrie_plugin.py and so the cowrie module can be imported. We can't prepend to the system PYTHONPATH with systemd, so i use this python one liner at stick /home/cowrie/cowrie on the front:

Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> ":".join(sys.path)
':/usr/lib/python2.7:/usr/lib/python2.7/plat-x86_64-linux-gnu:/usr/lib/python2.7/lib-tk:/usr/lib/python2.7/lib-old:/usr/lib/python2.7/lib-dynload:/usr/local/lib/python2.7/dist-packages:/usr/lib/python2.7/dist-packages'
>>> 

If you want to use a virtualenv this works exactly the same. All you need to dump is activate your virtualenv, dump sys.path as above, and set it in your PYTHONPATH.

We turn on NonBlocking so that systemd hands us sockets that are prepared for twisted async mode.

You can now turn the socket listeners on with:

$ sudo systemctl enable --now cowrie.socket
Created symlink from /etc/systemd/system/sockets.target.wants/cowrie.socket to /etc/systemd/system/cowrie.socket.

And they should be active:

$ sudo systemctl status cowrie.socket
● cowrie.socket - Cowrie SSH/Telnet sockets
   Loaded: loaded (/etc/systemd/system/cowrie.socket; enabled; vendor preset: enabled)
   Active: active (listening) since Wed 2017-05-03 00:04:33 PDT; 10s ago
   Listen: 0.0.0.0:22 (Stream)
           0.0.0.0:23 (Stream)

May 03 00:04:33 ubuntu systemd[1]: Closed Cowrie SSH/Telnet sockets.
May 03 00:04:33 ubuntu systemd[1]: Listening on Cowrie SSH/Telnet sockets.

If you are testing this in a local VM and don't have bots scanning every second then when you check the status of the service unit it will be inactive:

$ sudo systemctl status cowrie.service
● cowrie.service - Cowrie SSH and Telnet Honeypot
   Loaded: loaded (/etc/systemd/system/cowrie.service; disabled; vendor preset: enabled)
   Active: inactive (dead)

As we are doing socket activation thats completely normal - it should spring to life when you telnet to it:

$ telnet localhost
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
login: root
Password: 

And SSH should work too:

$ ssh localhost
The authenticity of host 'localhost (127.0.0.1)' can't be established.
RSA key fingerprint is SHA256:jboKg/NOh3GHazAj3A2PDCCeJM2lciVldFhENL5WYaM.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'localhost' (RSA) to the list of known hosts.
Password:
Password:
Password:

And there should be events in whatever logging backend you have configured:

$ cat /home/cowrie/cowrie/log/cowrie.json 
{"eventid": "cowrie.session.connect", "timestamp": "2017-05-03T07:08:51.638827Z", "session": "14dfd869", "message": "New connection: 127.0.0.1:40350 (127.0.0.1:22) [session: 14dfd869]", "src_port": 40350, "system": "cowrie.ssh.factory.CowrieSSHFactory", "isError": 0, "src_ip": "127.0.0.1", "dst_port": 22, "dst_ip": "127.0.0.1", "sensor": "ubuntu"}
{"eventid": "cowrie.client.version", "macCS": ["umac-64-etm@openssh.com", "umac-128-etm@openssh.com", "hmac-sha2-256-etm@openssh.com", "hmac-sha2-512-etm@openssh.com", "hmac-sha1-etm@openssh.com", "umac-64@openssh.com", "umac-128@openssh.com", "hmac-sha2-256", "hmac-sha2-512", "hmac-sha1"], "timestamp": "2017-05-03T07:08:51.640403Z", "session": "14dfd869", "kexAlgs": ["curve25519-sha256@libssh.org", "ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521", "diffie-hellman-group-exchange-sha256", "diffie-hellman-group-exchange-sha1", "diffie-hellman-group14-sha1", "ext-info-c"], "keyAlgs": ["ecdsa-sha2-nistp256-cert-v01@openssh.com", "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ssh-ed25519-cert-v01@openssh.com", "ssh-rsa-cert-v01@openssh.com", "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384", "ecdsa-sha2-nistp521", "ssh-ed25519", "rsa-sha2-512", "rsa-sha2-256", "ssh-rsa"], "message": "Remote SSH version: SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.1", "system": "HoneyPotSSHTransport,0,127.0.0.1", "isError": 0, "src_ip": "127.0.0.1", "version": "SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.1", "compCS": ["none", "zlib@openssh.com", "zlib"], "sensor": "ubuntu", "encCS": ["chacha20-poly1305@openssh.com", "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "aes256-gcm@openssh.com", "aes128-cbc", "aes192-cbc", "aes256-cbc", "3des-cbc"]}
{"eventid": "cowrie.login.failed", "username": "root", "timestamp": "2017-05-03T07:08:59.832262Z", "message": "login attempt [root/root] failed", "system": "SSHService 'ssh-userauth' on HoneyPotSSHTransport,0,127.0.0.1", "isError": 0, "src_ip": "127.0.0.1", "session": "14dfd869", "password": "root", "sensor": "ubuntu"}
{"eventid": "cowrie.login.failed", "username": "root", "timestamp": "2017-05-03T07:09:05.502725Z", "message": "login attempt [root/password] failed", "system": "SSHService 'ssh-userauth' on HoneyPotSSHTransport,0,127.0.0.1", "isError": 0, "src_ip": "127.0.0.1", "session": "14dfd869", "password": "password", "sensor": "ubuntu"}
{"eventid": "cowrie.session.closed", "timestamp": "2017-05-03T07:09:16.788595Z", "message": "Connection lost after 25 seconds", "system": "HoneyPotSSHTransport,0,127.0.0.1", "isError": 0, "src_ip": "127.0.0.1", "duration": 25.148725986480713, "session": "14dfd869", "sensor": "ubuntu"}

Using with virtualenv

Additionally install virtualenv:

sudo apt install python-virtualenv

Then instead of sudo pip install:

$ sudo su cowrie
cowrie@$ virtualenv /home/cowrie/cowrie/cowrie-env
Running virtualenv with interpreter /usr/bin/python2
New python executable in /home/cowrie/cowrie/cowrie-env/bin/python2
Also creating executable in /home/cowrie/cowrie/cowrie-env/bin/python
Installing setuptools, pkg_resources, pip, wheel...done.

cowrie@$ /home/cowrie/cowrie/cowrie-env/bin/pip install -r /home/cowrie/cowrie/requirements.txt 
Collecting twisted>=15.2.1 (from -r /home/cowrie/cowrie/requirements.txt (line 1))
  Downloading Twisted-17.1.0.tar.bz2 (3.0MB)
    100% |████████████████████████████████| 3.0MB 429kB/s 
<snip>
Installing collected packages: zope.interface, constantly, incremental, attrs, Automat, twisted, idna, asn1crypto, enum34, ipaddress, pycparser, cffi, cryptography, configparser, pyopenssl, gmpy2, pyasn1, pyasn1-modules, service-identity, pycrypto, python-dateutil, tftpy
Successfully installed Automat-0.5.0 asn1crypto-0.22.0 attrs-16.3.0 cffi-1.10.0 configparser-3.5.0 constantly-15.1.0 cryptography-1.8.1 enum34-1.1.6 gmpy2-2.0.8 idna-2.5 incremental-16.10.1 ipaddress-1.0.18 pyasn1-0.2.3 pyasn1-modules-0.0.8 pycparser-2.17 pycrypto-2.6.1 pyopenssl-17.0.0 python-dateutil-2.6.0 service-identity-16.0.0 tftpy-0.6.2 twisted-17.1.0 zope.interface-4.4.0

Then use this cowrie.service:

[Unit]
Description=Cowrie SSH and Telnet Honeypot
After=network.target
Requires=cowrie.socket

[Service]
Type=simple
User=cowrie
Group=cowrie
Environment=PYTHONPATH=/home/cowrie/cowrie:/home/cowrie/cowrie/cowrie-env/lib/python2.7:/home/cowrie/cowrie/cowrie-env/lib/python2.7/plat-x86_64-linux-gnu:/home/cowrie/cowrie/cowrie-env/lib/python2.7/lib-tk:/home/cowrie/cowrie/cowrie-env/lib/python2.7/lib-old:/home/cowrie/cowrie/cowrie-env/lib/python2.7/lib-dynload:/usr/lib/python2.7:/usr/lib/python2.7/plat-x86_64-linux-gnu:/usr/lib/python2.7/lib-tk:/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages:/home/cowrie/cowrie/cowrie-env/lib/python2.7/site-packages
Environment=PYTHONUNBUFFERED=true
ExecStart=/home/cowrie/cowrie/cowrie-env/bin/twistd -n -l - --umask 0077 --pidfile= cowrie
WorkingDirectory=/home/cowrie/cowrie/
NonBlocking=yes
Restart=always
TimeoutSec=300

[Install]
WantedBy=multi-user.target

The only difference is the PYTHONPATH and the path to twistd.

Using systemctl and journalctl

You can stop cowrie with systemctl stop cowrie but that will only stop the service, not the socket. And, well, we have socket activation that thats not going to achieve much!

$ sudo systemctl stop cowrie
Warning: Stopping cowrie.service, but it can still be activated by:
  cowrie.socket

$ sudo systemctl status cowrie
● cowrie.service - Cowrie SSH and Telnet Honeypot
   Loaded: loaded (/etc/systemd/system/cowrie.service; disabled; vendor preset: enabled)
   Active: inactive (dead) since Wed 2017-05-03 01:12:54 PDT; 5s ago
  Process: 13037 ExecStart=/usr/local/bin/twistd -n -l - --umask 00776 --pidfile= cowrie (code=exited, status=0/SUCCESS)
 Main PID: 13037 (code=exited, status=0/SUCCESS)

<snip>
May 03 01:12:54 ubuntu systemd[1]: Stopped Cowrie SSH and Telnet Honeypot.

$ telnet localhost
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
login: root
Password: 

So you will most likely want to stop both:

$ sudo systemctl stop cowrie.socket cowrie.service

You can see the status of the cowrie service with systemctl status:

$ sudo systemctl status cowrie.service
● cowrie.service - Cowrie SSH and Telnet Honeypot
   Loaded: loaded (/etc/systemd/system/cowrie.service; disabled; vendor preset: enabled)
   Active: active (running) since Wed 2017-05-03 00:15:57 PDT; 52min ago
 Main PID: 13037 (twistd)
   CGroup: /system.slice/cowrie.service
           └─13037 /usr/bin/python /usr/local/bin/twistd -n -l - --umask 00776 --pidfile= cowrie
    
May 03 00:15:58 ubuntu twistd[13037]: 2017-05-03T00:15:58-0700 [-] HoneyPotTelnetFactory starting on 23
May 03 00:15:58 ubuntu twistd[13037]: 2017-05-03T00:15:58-0700 [cowrie.telnet.transport.HoneyPotTelnetFactory#info] Starting factory <cowrie.telnet.transport.HoneyPotTelnetFactory instance at 0x7f4b33c5dd88>
May 03 00:15:58 ubuntu twistd[13037]: 2017-05-03T00:15:58-0700 [-] Ready to accept Telnet connections

You can also use sudo systemctl status cowrie for the same effect, but i like to be explicit when there is a cowrie.socket as well. Note that the correct port for telnet is shown, even though we don't mention port 23 in the cowrie config.

We can check on the socket listener with:

● cowrie.socket - Cowrie SSH/Telnet sockets
   Loaded: loaded (/etc/systemd/system/cowrie.socket; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2017-05-03 00:07:41 PDT; 1h 0min ago
   Listen: 0.0.0.0:22 (Stream)
           0.0.0.0:23 (Stream)

May 03 00:07:41 ubuntu systemd[1]: Closed Cowrie SSH/Telnet sockets.
May 03 00:07:41 ubuntu systemd[1]: Listening on Cowrie SSH/Telnet sockets.

You can tail your logs with journalctl:

$ journalctl -u cowrie -f
-- Logs begin at Tue 2017-05-02 23:45:24 PDT. --
May 03 00:15:58 ubuntu twistd[13037]: 2017-05-03T00:15:58-0700 [-] HoneyPotTelnetFactory starting on 23
May 03 00:15:58 ubuntu twistd[13037]: 2017-05-03T00:15:58-0700 [cowrie.telnet.transport.HoneyPotTelnetFactory#info] Starting factory <cowrie.telnet.transport.HoneyPotTelnetFactory instance at 0x7f4b33c5dd88>
May 03 00:15:58 ubuntu twistd[13037]: 2017-05-03T00:15:58-0700 [-] Ready to accept Telnet connections

Troubleshooting

Cowrie won't start, shows twistd usage help in logs

$ sudo systemctl status cowrie.service
● cowrie.service - Cowrie SSH and Telnet Honeypot
   Loaded: loaded (/etc/systemd/system/cowrie.service; disabled; vendor preset: enabled)
   Active: inactive (dead) since Wed 2017-05-03 00:05:04 PDT; 2s ago
  Process: 12762 ExecStart=/usr/local/bin/twistd -n -l - --umask 00776 --pidfile= cowrie (code=exited, status=0/SUCCESS)
 Main PID: 12762 (code=exited, status=0/SUCCESS)

May 03 00:05:02 ubuntu systemd[1]: cowrie.service: Service hold-off time over, scheduling restart.
May 03 00:05:02 ubuntu systemd[1]: Stopped Cowrie SSH and Telnet Honeypot.
May 03 00:05:02 ubuntu systemd[1]: Started Cowrie SSH and Telnet Honeypot.
May 03 00:05:02 ubuntu twistd[12735]: Usage: twistd [options]
May 03 00:05:02 ubuntu twistd[12735]: Options:
May 03 00:05:02 ubuntu twistd[12735]:       --savestats      save the Stats object rather than the text output of the
May 03 00:05:02 ubuntu twistd[12735]:                        profiler.
May 03 00:05:02 ubuntu twistd[12735]:   -o, --no_save        do not save state on shutdown
May 03 00:05:02 ubuntu twistd[12735]:   -e, --encrypted      The specified tap/aos file is encrypted.
May 03 00:05:02 ubuntu twistd[12735]:   -n, --nodaemon       don't daemonize, don't use default umask of 0077
<snip>

This means:

  • Twisted can't find /home/cowrie/cowrie/twisted/plugins/cowrie_plugin.py. Check permissions. Check the PYTHONPATH. See above for how to set your PYTHONPATH.

Address already in use

$ systemctl status cowrie.socket
● cowrie.socket - Cowrie SSH/Telnet sockets
   Loaded: loaded (/etc/systemd/system/cowrie.socket; enabled; vendor preset: enabled)
   Active: failed (Result: resources)
   Listen: 0.0.0.0:22 (Stream)
           0.0.0.0:23 (Stream)

May 03 00:03:27 ubuntu systemd[1]: cowrie.socket: Failed to listen on sockets: Address already in use
May 03 00:03:27 ubuntu systemd[1]: Failed to listen on Cowrie SSH/Telnet sockets.

This means:

  • You forgot to move your real ssh/telnet to a high port
  • You forgot to update cowrie.cfg to use the systemd: endpoints or it is now listening on a port and trying to use endpoints. You can't use both at the same time (unless they are different ports).

Connection hangs

$ telnet localhost
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

This means:

  • The number of times i've just forgot to set enabled = true in [telnet] - jeez
  • The cowrie service may be running but the sockets arent (make sure the unit file correctly states that cowrie.service requires cowrie.socket)
  • You may not have removed the PREROUTING iptables (if upgrading)
  • You may not have told cowrie to use systemd endpoints (or may have told it to use the wrong ones)
@dwasss
Copy link

dwasss commented May 3, 2017

This is helpful, thanks!

The cowrie service may be running but the sockets arent (make sure the unit file correctly states that cowrie.service requires cowrie.socket)

It looks like you don't have that line Requires=cowrie.socket in your example systemd service unit above.

Also, I set my PYTHONPATH to use a virtualenv, but I am now getting errors when trying to start cowrie:

-- Logs begin at Wed 2017-05-03 13:16:53 UTC. --
May 03 14:04:01 hp02 systemd[1]: Started Cowrie SSH and Telnet Honeypot.
May 03 14:04:01 hp02 twistd[2426]: Unhandled Error
May 03 14:04:01 hp02 twistd[2426]: Traceback (most recent call last):
May 03 14:04:01 hp02 twistd[2426]:   File "/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/twisted/application/app.py", line 657, in run
May 03 14:04:01 hp02 twistd[2426]:     config.parseOptions()
May 03 14:04:01 hp02 twistd[2426]:   File "/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/twisted/application/app.py", line 624, in parseOptions
May 03 14:04:01 hp02 systemd[1]: cowrie.service: Service hold-off time over, scheduling restart.
May 03 14:04:01 hp02 systemd[1]: Stopped Cowrie SSH and Telnet Honeypot.
May 03 14:04:01 hp02 systemd[1]: cowrie.service: Start request repeated too quickly.
May 03 14:04:01 hp02 systemd[1]: Failed to start Cowrie SSH and Telnet Honeypot.

Some more parts of the error log:

...
May 03 14:03:59 hp02 twistd[2398]:   File "/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/twisted/python/u
May 03 14:03:59 hp02 twistd[2398]:     for (cmd, short, parser, desc) in self.subCommands:
May 03 14:03:59 hp02 twistd[2398]:   File "/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/twisted/applicat
May 03 14:03:59 hp02 twistd[2398]:     for plug in sorted(plugins, key=attrgetter('tapname')):
May 03 14:03:59 hp02 twistd[2398]: --- <exception caught here> ---
May 03 14:03:59 hp02 twistd[2398]:   File "/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/twisted/plugin.p
May 03 14:03:59 hp02 twistd[2398]:     adapted = interface(plugin, None)
May 03 14:03:59 hp02 twistd[2398]:   File "/usr/lib/python2.7/dist-packages/zope/interface/interface.py", line 467, in _call
May 03 14:03:59 hp02 twistd[2398]:     return conform(self)
May 03 14:03:59 hp02 twistd[2398]:   File "/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/twisted/plugin.p
May 03 14:03:59 hp02 twistd[2398]:     return self.load()
May 03 14:03:59 hp02 twistd[2398]:   File "/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/twisted/plugin.p
May 03 14:03:59 hp02 twistd[2398]:     return namedAny(self.dropin.moduleName + '.' + self.name)
May 03 14:03:59 hp02 twistd[2398]:   File "/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/twisted/python/r
May 03 14:03:59 hp02 twistd[2398]:     topLevelPackage = _importAndCheckStack(trialname)
May 03 14:03:59 hp02 twistd[2398]:   File "/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/twisted/python/r
May 03 14:03:59 hp02 twistd[2398]:     reraise(excValue, excTraceback)
May 03 14:03:59 hp02 twistd[2398]:   File "/home/cowrie/cowrie/twisted/plugins/cowrie_plugin.py", line 48, in <module>
May 03 14:03:59 hp02 twistd[2398]:     from cowrie.core.config import readConfigFile
May 03 14:03:59 hp02 twistd[2398]:   File "/home/cowrie/cowrie/cowrie/core/config.py", line 8, in <module>
May 03 14:03:59 hp02 twistd[2398]:     import configparser
May 03 14:03:59 hp02 twistd[2398]:   File "/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/configparser.py"
May 03 14:03:59 hp02 twistd[2398]:     from backports.configparser import (
May 03 14:03:59 hp02 twistd[2398]: exceptions.ImportError: No module named backports.configparser
May 03 14:03:59 hp02 twistd[2398]: Usage: twistd [options]
...

This one works fine:
Environment=PYTHONPATH=/home/cowrie/cowrie:/usr/lib/python2.7:/usr/lib/python2.7/plat-x86_64-linux-gnu:/usr/lib/python2.7/lib-tk:/usr/lib/python2.7/lib-old:/usr/lib/python2.7/lib-dynload:/home/cowrie/.local/lib/python2.7/site-packages:/usr/local/lib/python2.7/dist-packages:/usr/lib/python2.7/dist-packages

This one causes the error above:
Environment=PYTHONPATH=/home/cowrie/cowrie:/home/cowrie/cowrie/cowrie-env/lib/python2.7:/home/cowrie/cowrie/cowrie-env/lib/python2.7/plat-x86_64-linux-gnu:/home/cowrie/cowrie/cowrie-env/lib/python2.7/lib-tk:/home/cowrie/cowrie/cowrie-env/lib/python2.7/lib-old:/home/cowrie/cowrie/cowrie-env/lib/python2.7/lib-dynload:/usr/lib/python2.7:/usr/lib/python2.7/plat-x86_64-linux-gnu:/usr/lib/python2.7/lib-tk:/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages:/home/cowrie/cowrie/cowrie-env/lib/python2.7/site-packages

Not sure why...

@Jc2k
Copy link
Author

Jc2k commented May 3, 2017

Good spot re: the Requires. It works without it if cowrie.socket is started and cowrie.service isn't started - socket activation for cowrie.socket will implicitly look for cowrie.service unless told otherwise. The Requires is required so that you can directly invoke systemctl start cowrie.service. Ah the joy of dep graphs. Fixed.

Will see if I can recreate the virtualenv issue.

@Jc2k
Copy link
Author

Jc2k commented May 3, 2017

May 03 14:03:59 hp02 twistd[2398]:   File "/home/cowrie/cowrie/cowrie/core/config.py", line 8, in <module>
May 03 14:03:59 hp02 twistd[2398]:     import configparser
May 03 14:03:59 hp02 twistd[2398]:   File "/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/configparser.py"
May 03 14:03:59 hp02 twistd[2398]:     from backports.configparser import (
May 03 14:03:59 hp02 twistd[2398]: exceptions.ImportError: No module named backports.configparser

So configparser is a back port module - upstream is here: https://bitbucket.org/ambv/configparser

If it can find configparser (it has) then its very surprising it can't find backports.configparser. They should be in the same folder - in this case i'd expect to see the following files:

  • /home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/configparser.py
  • /home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/backports/__init__.py
  • /home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/backports/configparser.py

@dwasss
Copy link

dwasss commented May 3, 2017

Neither one of these ExecStart works when I use the virtualenv's PYTHONPATH:

ExecStart=/home/cowrie/.local/bin/twistd -n -l - --umask 0077 --pidfile= cowrie
#ExecStart=/home/cowrie/.local/bin/twistd -n -l - --umask 0077 --pidfile= cowrie -c cowrie.cfg

Part of the error I get is:

May 03 14:59:50 hp02 twistd[3080]: /home/cowrie/.local/bin/twistd: Unknown command: cowrie
May 03 14:59:50 hp02 systemd[1]: cowrie.service: Service hold-off time over, scheduling restart.
May 03 14:59:50 hp02 systemd[1]: Stopped Cowrie SSH and Telnet Honeypot.
May 03 14:59:50 hp02 systemd[1]: Started Cowrie SSH and Telnet Honeypot.
May 03 14:59:50 hp02 twistd[3089]: Unhandled Error
May 03 14:59:50 hp02 twistd[3089]: Traceback (most recent call last):
May 03 14:59:50 hp02 twistd[3089]:   File "/home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/twisted/application/app.py", line 657, in run
May 03 14:59:51 hp02 systemd[1]: cowrie.service: Service hold-off time over, scheduling restart.

@dwasss
Copy link

dwasss commented May 3, 2017

For your last comment:

xxx@xxx:~$ ls -la /home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/backports/
total 12
drwxrwxr-x  3 cowrie cowrie 4096 Oct 25  2016 .
drwxrwxr-x 60 cowrie cowrie 4096 Apr 25 15:35 ..
drwxrwxr-x  2 cowrie cowrie 4096 Oct 25  2016 configparser
xxx@xxx:~$ ls -la /home/cowrie/cowrie/cowrie-env/local/lib/python2.7/site-packages/backports/configparser/
total 136
drwxrwxr-x 2 cowrie cowrie  4096 Oct 25  2016 .
drwxrwxr-x 3 cowrie cowrie  4096 Oct 25  2016 ..
-rw-rw-r-- 1 cowrie cowrie  5248 Oct 25  2016 helpers.py
-rw-rw-r-- 1 cowrie cowrie  8034 Oct 25  2016 helpers.pyc
-rw-rw-r-- 1 cowrie cowrie 55060 Oct 25  2016 __init__.py
-rw-rw-r-- 1 cowrie cowrie 55543 Oct 25  2016 __init__.pyc

@Jc2k
Copy link
Author

Jc2k commented May 3, 2017

Ahh theres a thought -

ExecStart=/home/cowrie/.local/bin/twistd

should probably be

ExecStart=/home/cowrie/cowrie/cowrie-env/bin/twistd

Just building a vm now

@Jc2k
Copy link
Author

Jc2k commented May 3, 2017

@dwasss i've added a section of virtualenv above. You have to tell ExecStart to use the twistd in the virtualenv as well as modifying the PYTHONPATH.

@dwasss
Copy link

dwasss commented May 3, 2017

Yes, that was it! I changed it to ExecStart=/home/cowrie/cowrie/cowrie-env/bin/twistd -n -l - --umask 0077 --pidfile= cowrie -c cowrie.cfg and everything is fine now with the virtualenv. Thank you!

I think all of my problems are finally resolved 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment