The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Net::Dropbear::SSHd - Embed and control a Dropbear SSH server inside of perl

SYNOPSIS

  use Net::Dropbear::SSHd;
  
  Net::Dropbear::XS::gen_key($key_filename);
  
  my $sshd = Net::Dropbear::SSHd->new(
    addrs      => '2222',
    keys       => $key_filename,
    hooks      => {
      on_log => sub
      {
        my $priority = shift;
        my $msg      = shift;
        warn( "$msg\n" );
        return HOOK_CONTINUE;
      },
    }
  );
  
  $sshd->run;
  $sshd->wait;

DESCRIPTION

Net::Dropbear::SSHd allows you to embed and control an SSH server (using Dropbear) from perl.

Motivation

Maybe you're asking yourself why you'd want to do that? Imagine that you want to run a service where you let users run remote commands over SSH, say SFTP or git. Also imagine that you'd like maintain the users or public keys in a database instead of in a file. A good example of this behavior would be Github and other cloud-based git-over-ssh solutions.

I'm pretty confident that one could get OpenSSH to do this, but I saw a couple problems:

The user must be a real user

Any user that wants to connect must be a real user at the OS level. Managing multiple users, let alone millions, is a nightmare.

OpenSSH really likes running as root

Until recently, running as non-root was even possible. It's now possible, but a lot of interesting features are restricted.

Authorized keys can be provided through a script owned by root

A continuation of the point above, but in order to enable OpenSSH to verify a key, a script can be provided. This script (and all directories leading to the script) must be owned by root.

OpenSSH (and SSH) have a lot of options

And while that is a good thing in general, in this particular case I was not confident that I could tune all the options correctly to make sure I wasn't completely securing the system.

I really didn't want to provide outside users with a clever way to gain access to my machine. That's where this module comes into play. The goal of Net::Dropbear::SSHd is that you can control the entire lifecycle of SSHd, including which usernames are accpeted, which public keys are authorized and what commands are ran.

CONSTRUCTOR

new

  my $sshd = Net::Dropbear::SSHd({ %params });

Returns a new Net::Dropbear::SSHd object.

Attributes

addrs

A string or an array of addresses to bind to. Default: Nothing

keys

An array of strings that are the server keys for Dropbear. Default: Generate keys automatically

hooks

A hashref of coderef's that get called during key points of the SSH server session. See "Hooks".

Dropbear options

debug

If Dropbear is complied with trace debuging turned on (not the default), turning this on will enable Dropbear's debugging information to be dumped.

Default: off

forkbg

Turning the forkbg option on means that Dropbear will fork into the background. Since Net::Dropbear::SSHd forks to run the main Dropbear code, doing this second fork would seem redundant.

Default: off

usingsyslog

Turning the usingsyslog option on means Dropbear will use syslog to output it's logs. Regardless of this setting, the on_log hook will still be called.

Default: off

norootlogin

Turning the norootlogin option on means that root can not login.

Default: on

noauthpass

Turning the noauthpass option on means that password authentication is not allowed

Default: on

norootpass

Turning the norootpass option on means that root cannot authenticate using a password.

Default: on

allowblankpass

Turning the allowblankpass option on means that if the SSH client requests it, Dropbear will authenticate someone with a blank password.

Default: off

delay_hostkey

Turning the delay_hostkey option on tells Dropbear to not generate hostkey files until the first user connects. This allows for faster startup times the very first time in exchange for a delayed connection for the very first user.

Default: off

domotd

Turning on the domotd option means that when an interactive session is started, the message of the day is sent.

Default: off

noremotetcp

Turning on the noremotetcp option means that Dropbear will not create remote forwarded TCP tunnels.

Default: on

nolocaltcp

Turning on the nolocaltcp option means that Dropbear will not create locally forwarded TCP tunnels.

Default: on

Hooks

During the run of Dropbear, Net::Dropbear::SSHd hooks into certain points of the processing. With these hooks, the outcome of Dropbear can be changed. Each hook can return one of the hook constants: "HOOK_COMPLETE", "HOOK_CONTINUE" or "HOOK_FAILURE". Unless otherwise noted, returning "HOOK_CONTINUE" will result in Dropbear continuing as though the hook hadn't been called.

on_log(priority, message)

The on_log hook is called when Dropbear logs anything.

HOOK_COMPLETE - No more logging will take place
HOOK_FAILURE - Logging will continue as normal
on_start()

The on_start hook is called after Dropbear is done initalizing.

HOOK_COMPLETE - Identical to HOOK_CONTINUE
HOOK_FAILURE - Dropbear will exit
on_username(username)

The on_username hook is called when a username is given. Returning anything but HOOK_CONTINUE from this will prevent "on_passwd_fill" or "on_shadow_fill" from being called.

HOOK_COMPLETE - The username is acceptable and dummy entries are used for the password file
HOOK_FAILURE - The username is rejected
on_passwd_fill(Net::Dropbear::XS::AuthState, username)

The on_passwd_fill hook is called when Dropbear is filling in information for a user from the passwd file. The Net::Dropbear::XS::AuthState paramater is an object that can be manipulated to fill in information for Dropbear. See Net::Dropbear::XS::AuthState. If any AuthState data is left invalid, Dropbear will exit.

HOOK_COMPLETE - The AuthState object should be used as the passwd information.
HOOK_FAILURE - The passwd information is invalid and the user connection will be rejected.
on_shadow_fill(crypt_password, pw_name)

The on_shadow_fill hook is called when the shadow file is consulted for a users password. Note that this is called even if HOOK_COMPLETE is returned from on_passwd_fill. The first paramter (crypt_password) is mutable and can be used to set what the user's crypted password is. If the crypt_password is invalid (null), Dropbear will exit.

HOOK_COMPLETE - The shadow file will not be consulted for the given user
HOOK_FAILURE - Ignored
on_check_pubkey(authkeys, pw_name)

The on_check_pubkey hook is called right before the the public keys for a user is checked. The first paramater, authkeys, is an string that can be populated with an authorized_keys(8) file and it will be used to authenticate the user given with pw_name.

HOOK_COMPLETE - Identical to HOOK_CONTINUE
HOOK_FAILURE - The public keys could not be retrieved and will not be checked.
on_new_channel(on_new_channel)

The on_new_channel hook is called when the client requests a new channel. The first paramater, on_new_channel, will contain the channel type as a string.

HOOK_COMPLETE - Identical to HOOK_CONTINUE
HOOK_FAILURE - The channel is denied with SSH_OPEN_ADMINISTRATIVELY_PROHIBITED
on_chansess_command(Net::Dropbear::XS::SessionAccept)

The on_chansess_command hook is called when a new command is being requested by the client. The first paramater, Net::Dropbear::XS::SessionAccept, is an object that should be used to let Dropbear know how to interact with the channel. See Net::Dropbear::XS::SessionAccept for more details.

HOOK_COMPLETE - No attempts will be made to start the command specified
HOOK_CONTINUE - The values from Net::Dropbear::XS::SessionAccept will be copied into Dropbear and used in Dropbear's default operations
HOOK_FAILURE - The command session will behave as though the command had vailed

METHODS

run

Call $sshd-run> to start Dropbear.

child

If Dropbear has been started, then this will return the Child::Link::Proc object of the child process. If Dropbear is not running, this will return undef. In the child process this will be undef as well.

comm

The comm method is a convience for both parent and child processes. This contains a two-way socket between the parent and child (and sub-children) processes. This is a AF_UNIX socket, which means you can pass new file handles between the processes.

is_running

Returns true if Dropbear is running, false if it's not.

kill

This will stop Dropbear.

wait

This waits for Dropbear to exit after it is sent the kill signal.

CONSTANTS

The constants below are exported by default.

HOOK_COMPLETE

This is used to indicate that a hook is done and not to use Dropbear's default operations.

HOOK_CONTINUE

This is used to indicate that the hook has decided not to do anything.

HOOK_FAILURE

This is used to indicate that the hook has failed and Dropbear should not continue.

CHILD PROCESSES

Since Dropbear is a program itself, it is ran as a child process. Each connection will also have it's own child process.

AUTHOR

Jon Gentle <atrodo@cpan.org>

COPYRIGHT

Copyright 2015- Jon Gentle

LICENSE

This is free software. You may redistribute copies of it under the terms of the Artistic License 2 as published by The Perl Foundation.

This includes a complete copy of Dropbear that is patched and used. The majority of Dropbear is Copyright (c) 2002-2014 Matt Johnston under the MIT license. See https://matt.ucc.asn.au/dropbear/dropbear.html for details about Dropbear and it's license.