Sometimes there's a need to use our shell in places where the security policy is very restrictive and access is only possible to the most popular services. This is where applications that emulate a terminal in the browser come to our aid. As far as I know, there are three such programs on the market: AjaxTerm, AnyTerm, and ShellinABox. The first two require the user to install additional components, i.e. an Apache module and, in the case of AjaxTerm, the Python interpreter; also, the emulation of full-screen applications isn't perfect. The third program, ShellinABox, seems to be the best solution. Arguments in its favor:
- it's a self-sufficient application (requires the OpenSSL package), it doesn't even require a web server.
- thanks to full support for the VT100 terminal standard, it handles full-screen applications perfectly (Midnight Commander, htop, top, ekg)
- SSL support
- simple configuration
- ...and finally the most important thing: it's really fast
- support for Polish characters (UTF-8 encoding)
Installing ShellinABox is simple. On the official ShellinABox website we'll find deb packages as well as source for compiling it ourselves.
The OpenSSL library is required to run it. The file ShellinABoxd is used to run our terminal; the Debian/Ubuntu package installs a script in the /etc/init.d/ShellinABoxd directory.
After starting, ShellinABox listens on all interfaces on port 4200, which wasn't necessarily what I wanted. We can force it to only work on localhost by adding
the --localhost-only option at startup, or on Debian by adding ShellinABox_ARGS=--localhost-only to the /etc/default/ShellinABox file.
Due to its young age, it suffers from childhood diseases. The biggest inconvenience is an issue with the SSL certificate leading to the program hanging. If we want to connect over https, then in theory
ShellinABox should generate a certificate itself before its first run (with the help of OpenSSL), but it doesn't. We have to generate it ourselves and copy it to the program's directory, which on Debian
is the directory /var/lib/ShellinABox. I haven't noticed this problem with the version from the official Debian repositories.
I decided against encryption in ShellinABox in favor of SSL on the web server, adding another layer of security in the form of password-based access authorization. In my solution I adopted the following assumptions:
ShellinABox runs without encryption, only on the local host; the rest of the functionality, such as SSL, password access, and exposing it externally (reverse proxy), is handled by nginx. Another advantage of this solution is convenience -
we don't have to type http://host:port_number into the browser, we can just use http://host .
Configuring ShellinABox
- To restrict listening to the local interface on port 4200 and disable encryption, we edit the file /etc/default/ShellinABox
Configuring a reverse proxy using Nginx as an example
The example is based on configuring a virtual host to which we'll connect to reach our emulator. Remember to reconfigure your DNS.
- Assuming that our domain is: dom.pl and the subdomain for ShellinABox is shl, we need to edit the dom.pl zone file, adding an entry (DNS server: BIND), and update the Serial:
- We go to the /etc/nginx/sites-available/ directory and create the file shl: file shl
ShellinABox_PORT=4200 #set the port
ShellinABox_ARGS=--localhost-only #restrict listening
ShellinABox_ARGS=--disable-ssl #disable encryption
After making changes, restart the program: /etc/init.d/ShellinABox
shl IN A our.ip
after the changes: rndc reload
server {
listen 80; # we listen on the standard port 80
server_name shl.dom.pl; # nginx itself will redirect us to https
if ($host = 'shl.dom.pl' ) {
rewrite ^/(.*)$ https://shl.ulos.pl/$1 permanent;
}
access_log /var/log/nginx/shl.access_log;
error_log /var/log/nginx/shl.error_log;
}
server{ # ssl configuration
listen 443;
ssl on;
server_name shl.ulos.pl;
ssl_certificate /etc/nginx/ssl/ssl.crt; # we need to generate a certificate and key
ssl_certificate_key /etc/nginx/ssl/ssl.key;
access_log /var/log/nginx/shl_ssl.access_log;
error_log /var/log/nginx/shl_ssl.error_log;
# Main location
location / {
proxy_pass http://127.0.0.1:4200/; # we provide the ip:port on which ShellinABox is running
proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
auth_basic "Restricted"; # additional security - authorization via password
auth_basic_user_file /etc/nginx/.htpasswd;
}
}
At this point we have a solution that's much better in terms of functionality and cheaper than commercial offerings, which are mostly based on AjaxTerm