c0d3 :: j0rg3

A collection of tips, tricks and snips. A proud Blosxom weblog. All code. No cruft.

Fri, 17 Feb 2017

The making of a Docker: Part I - Bitmessage GUI with SSH X forwarding

Lately, I’ve been doing a lot of work from a laptop running Kali. Engaged in pursuit of a new job, I’m brushing up on some old tools and skills, exploring some bits that have changed.

My primary desktop rig is currently running Arch because I love the fine grain control and the aggressive releases. Over the years, I’ve Gentoo’d and Slacked, Crunchbanged, BSD’d, Solarised, et cet. And I’ve a fondness for all of them, especially the security-minded focus of OpenBSD. But, these days we’re usually on Arch or Kali. Initially, I went with Black Arch on the laptop but I felt the things and ways I was fixing things were too specific to my situation to be good material for posts.

Anyway, I wanted to get Bitmessage running, corresponding to another post I have in drafts. On Kali, it wasn’t going well so I put it on the Arch box and just ran it over the network. A reasonable solution if you’re in my house but also the sort of solution that will keep a hacker up at night.

If you’re lucky, there’s someone maintaining a package for the piece of software that you want to run. However, that’s often not the case.

If I correctly recall, to “fix” the problem with Bitmessage on Kali would’ve required the manual installation an older version of libraries that were already present. Those libraries should, in fact, be all ebony and ivory, living together in harmony. However, I just didn’t love the idea of that solution. I wanted to find an approach that would be useful on a broader scale.

Enter containerization/virtualization!

Wanting the lightest solution, I quickly went to Docker and realized something. I have not before built a Docker container for a GUI application. And Bitmessage’s CLI/daemon mode doesn’t provide the fluid UX that I wanted. Well, the easy way to get a GUI out of a Docker container is to forward DISPLAY as an evironment variable (i.e., docker run -e DISPLAY=$DISPLAY). Splendid!

Except that it doesn’t work on current Kali which is using QT4. There’s a when graphical apps are run as root and though it is fixed in QT5, we are using current Kali. And that means we are, by default, uid 0 and QT4.

I saw a bunch of workarounds that seemed to have spotty (at best) rates of success including seting QT’s graphics system to Native and giving Xorg over to root. They, mostly, seemed to be cargo cult solutions.

What made the most sense to my (generally questionable) mind was to use X forwarding. Since I had already been running Bitmessage over X forwarding from my Arch box, I knew it should work just the same.

To be completely truthful, the first pass I took at this was with Vagrant mostly because it’s SO easy. Bring up your Vagrant Box and then:
vagrant ssh -- -X
Viola!

Having proof of concept, I wanted a Docker container. The reason for this is practical. Vagrant, while completely awesome, has substantially more overhead than Docker by virtualizing the kernel. We don’t want a separate kernel running for each application. Therefore Docker is the better choice for this project.

Also, we want this whole thing to be seemless. We want to run the command bitmessage and it should fire up with minimal awkwardness and hopefully no extra steps. That is we do not want to run the Docker container then SSH into it and execute Bitmessage as individual steps. Even though that’s going to be how we begin.

The Bitmessage wiki accurately describes how to install the software so we’ll focus on the SSH setup. Though when we build the Dockerfile we will need to add SSH to the list from the wiki.

We’re going to want the container to start so that the SSH daemon is ready. Until then we can’t SSH (with X forwarding) into the container. Then we’ll want to use SSH to kick off the Bitmessage application, drawing the graphical interface using our host system’s X11.

We’re going to take advantage of Docker’s -v --volume option which allows us to specify a directory on our host system to be mounted inside our container. Using this feature, we’ll generate our SSH keys on the host and make them automatically available inside the container. We’ll tuck the keys inside the directory that Bitmessage uses for storing its configuration and data. That way Bitmessage’s configuration and stored messages can be persistent between runs — and all of your pieces are kept in a single place.

When we generate the container /etc/ssh/sshd_config is configured to allow root login without password only (i.e., using keys). So here’s how we’ll get this done:
mkdir -p ~/.config/PyBitmessage/keys #Ensure that our data directories exist
cd ~/.config/PyBitmessage/keys
ssh-keygen -b 4096 -P "" -C $"$(whoami)@$(hostname)-$(date -I)" -f docker-bitmessage-keys #Generate our SSH keys
ln -fs docker-bitmessage-keys.pub authorized_keys #for container to see pubkey

Build our container (sources available at Github and Docker) and we’ll make the script to handle Bitmessage to our preferences. #!/bin/bash
# filename: bitmessage
set -euxo pipefail

# open Docker container:
# port 8444 available, sharing local directories for SSH and Bitmessage data
# detatched, interactive, pseudo-tty (-dit)
# record container ID in $DID (Docker ID)
DID=$(docker run -p 8444:8444 -v ~/.config/PyBitmessage/:/root/.config/PyBitmessage -v ~/.config/PyBitmessage/keys/:/root/.ssh/ -dit j0rg3/bitmessage-gui bash)

# find IP address of new container, record in $DIP (Docker IP)
DIP=$(docker inspect $DID | grep IPAddress | cut -d '"' -f 4)

# pause for one second to allow container's SSHD to come online
sleep 1

# SSH into container and execute Bitmessage
ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oIdentityFile=~/.config/PyBitmessage/keys/docker-bitmessage-keys -X $DIP ./PyBitmessage/src/bitmessagemain.py

# close container if Bitmessage is closed
docker kill $DID

Okay, let’s make it executable: chmod +x bitmessage

Put a link to it where it can be picked up system-wide: ln -fs ~/docker-bitmessage/bitmessage /usr/local/bin/bitmessage

There we have it! We now have a functional Bitmessage inside a Docker container. \o/

In a future post we’ll look at using eCryptfs to further protect our Bitmessage data stores.

  Project files: Github and Docker


Tags: , , , , , , , , , , ,
Permalink: 20170217.making.a.docker.bitmessage

Mon, 02 Jan 2017

Securing a new server

Happy new year! New year means new servers, right?

That provides its own set of interesting circumstances!

The server we’re investigating in this scenario was chosen for being a dedicated box in a country that has quite tight privacy laws. And it was a great deal offered on LEB.

So herein is the fascinating bit. The rig took a few days for the provider to set up and, upon completion, the password for SSHing into the root account was emailed out. (o_0)

In very security-minded considerations, that means that there was a window of opportunity for bad guys to work on guessing the password before its owner even tuned in. That window remains open until the server is better secured. Luckily, there was a nice interface for reinstalling the OS permitting its purchaser to select a password.

My preferred approach was to script the basic lock-down so that we can reinstall the base OS and immediately start closing gaps.


In order:

  • Set up SSH keys (scripted)
  • Disable password usage for root (scripted)
  • Install and configure IPset (scripted. details in next post)
  • Install and configure fail2ban
  • Install and configure PortSentry

  • In this post, we’re focused on the first two steps.


    The tasks to be handled are:

  • Generate keys
  • Configure local SSH to use key
  • Transmit key to target server
  • Disable usage of password for ‘root’ account

  • We’ll use ssh-keygen to generate a key — and stick with RSA for ease. If you’d prefer ECC then you’re probably reading the wrong blog but feel encouraged to contact me privately.

    The code:

    #!/bin/bash
    #configure variables
    remote_host="myserver.com"
    remote_user="j0rg3"
    remote_pass="thisisaratheraquitecomplicatedpasswordbatterystaple" # https://xkcd.com/936/
    local_user=`whoami`
    local_host=`hostname`
    local_date=`date -I`
    local_filename=~/.ssh/id_rsa@$remote_host

    #generate key without passphrase
    ssh-keygen -b 4096 -P "" -C $local_user@local_host-$local_date -f $local_filename

    #add reference to generated key to local configuration
    printf '%s\n' "Host $remote_host" "IdentityFile $local_filename" >> ~/.ssh/config

    #copy key to remote host
    sshpass -p $remote_pass ssh-copy-id $remote_user@$remote_host

    #disable password for root on remote
    ssh $remote_user@$remote_host "cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak && sed -i '0,/RE/s/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config"

    We just run this script soon as the OS is reinstalled and we’re substantially safer. As a Deb8 install, quickly pulling down fail2ban and PortSentry makes things quite a lot tighter.

    In another post, we’ll visit the 2017 version of making a DIY script to batten the hatches using a variety of publicly provided blocklists.

    Download here:
        ssh_quick_fix.sh


    Tags: , , , ,
    Permalink: 20170102.securing.a.new.server

    Sun, 13 Jul 2014

    Simple Protection with iptables, ipset and Blacklists

    Seems I’ve always just a few more things going on than I can comfortably handle. One of those is an innocent little server holding the beginnings of a new project.

    If you expose a server to the Internet, very quickly your ports are getting scanned and tested. If you’ve an SSH server, there are going to be attempts to login as ‘root’ which is why it is ubiquitously advised that you disable root login. Also why many advise against allowing passwords at all.

    We could talk for days about improvements; it’s usually not difficult to introduce some form of two-factor authentication (2FA) for sensitive points of entry such as SSH. You can install monitoring software like Logwatch which can summarize important points from your logs, such as: who has logged via SSH, how many times root was used, etc.

    DenyHosts and Fail2ban are very great ways to secure things, according to your needs.

    DenyHosts works primarily with SSH and asks very little from you in way of configuration, especially if you’re using a package manager to install a version that is configured for the distribution on which you’re working. If you’re installing from source you may need to find where are your SSH logs (e.g., /var/log/secure, /var/log/auth.log). It’s extremely easy to set up DenyHosts to synchronize so that you’re automatically blocking widely-known offenders whether or not they’re after your server.

    In contrast, Fail2ban is going to take more work to get set up. However, it is extremely configurable and works with any log file you point it toward which means that it can watch anything (e.g., FTP, web traffic, mail traffic). You define your own jails which means you can ban problematic IP addresses according to preference. Ban bad HTTP attempts from HTTP only or stick their noses in the virtual corner and don’t accept any traffic from them until they’ve served their time-out by completely disallowing their traffic. You can even use Fail2ban to scan its own logs, so repeating offenders can be locked out for longer.

    Today we’re going to assume that you’ve a new server that shouldn’t be seeing any traffic except from you and any others involved in the project. In that case, you probably want to block traffic pretty aggressively. If you’ve physical access to the server (or the ability to work with staff at the datacenter) then it’s better to err in the direction of accidentally blocking good guys than trying to be overly fault-tolerant.

    The server we’re working on today is a Debian Wheezy system. It has become a common misconception that Ubuntu and Debian are, intents and purposes, interchangeable. They’re similar in many respects and Ubuntu is great preparation for using Debian but they are not the same. The differences, I think, won’t matter for this exercise but I am unsure because this was written using Wheezy.

    Several minutes after bringing my new server online, I started seeing noise in the logs. I was still getting set up and really didn’t want to stop and take protective measures but there’s no point in securing a server after its been compromised. The default Fail2ban configuration was too forgiving for my use. It was scanning for 10 minutes and banning for 10 minutes. Since only a few people should be accessing this server, there’s no reason for anyone to be trying a different password every 15 minutes (for hours).

    I found a ‘close-enough’ script and modified it. Here, we’ll deal with a simplified version.

    First, lets create a name for these ne’er-do-wells in iptables:
    iptables -N bad_traffic

    For this one, we’ll use Perl. We’ll look at our Apache log files to find people sniffing ‘round and we’ll block their traffic. Specifically, we’re going to check Apache’s ‘error.log’ for the phrases ‘File does not exist’ and ‘client denied by server configuration’ and block people causing those errors. This would be excessive for servers intended to serve the general populace. For a personal project, it works just fine as a ‘DO NOT DISTURB’ sign.


    #!/usr/bin/env perl
    use strict;
    use POSIX qw(strftime);

    my $log = ($ARGV[0] ? $ARGV[0] : "/var/log/apache2/error.log");
    my $chain = ($ARGV[1] ? $ARGV[1] : "bad_traffic");

    my @bad = `grep -iE 'File does not exist|client denied by server configuration' $log |cut -f8 -d" " | sed 's/]//' | sort -u`;
    my @ablk = `/sbin/iptables -S $chain|grep DROP|awk '{print $4}'|cut -d"/" -f1`;

    foreach my $ip (@bad) {
    if (!grep $_ eq $ip, @ablk) {
    chomp $ip;
    `/sbin/iptables -A $chain -s $ip -j DROP`;
    print strftime("%b %d %T",localtime(time))." badht: blocked bad HTTP traffic from: $ip\n";
    }
    }

    That gives us some great, utterly unforgiving, blockage. Looking at the IP addresses attempting to pry, I noticed that most of them were on at least one of the popular block-lists.

    So let’s make use of some of those block-lists! I found a program intended to apply those lists locally but, of course, it didn’t work for me. Here’s a similar program; this one will use ipset for managing the block-list though only minor changes would be needed to use iptables as above:

    #!/bin/bash
    IP_TMP=ip.tmp
    IP_BLACKLIST_TMP=ip-blacklist.tmp

    IP_BLACKLIST=ip-blacklist.conf

    WIZ_LISTS="chinese nigerian russian lacnic exploited-servers"

    BLACKLISTS=(
    "http://danger.rulez.sk/projects/bruteforceblocker/blist.php" # BruteForceBlocker IP List
    "http://rules.emergingthreats.net/blockrules/compromised-ips.txt" # Emerging Threats - Compromised IPs
    "http://www.spamhaus.org/drop/drop.txt" # Spamhaus Don't Route Or Peer List (DROP)
    "http://www.spamhaus.org/drop/edrop.txt" # Spamhaus Don't Route Or Peer List (DROP) Extended
    "http://cinsscore.com/list/ci-badguys.txt" # C.I. Army Malicious IP List
    "http://www.openbl.org/lists/base.txt" # OpenBL.org 90 day List
    "http://www.autoshun.org/files/shunlist.csv" # Autoshun Shun List
    "http://lists.blocklist.de/lists/all.txt" # blocklist.de attackers
    )

    for address in "${BLACKLISTS[@]}"
    do
    echo -e "\nFetching $address\n"
    curl "$address" >> $IP_TMP
    done

    for list in $WIZ_LISTS
    do
    wget "http://www.wizcrafts.net/$list-iptables-blocklist.html" -O - >> $IP_TMP
    done

    wget 'http://wget-mirrors.uceprotect.net/rbldnsd-all/dnsbl-3.uceprotect.net.gz' -O - | gunzip | tee -a $IP_TMP

    grep -o '^[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}[/][0-9]\{1,3\}' $IP_TMP | tee -a $IP_BLACKLIST_TMP
    grep -o '^[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}[^/]' $IP_TMP | tee -a $IP_BLACKLIST_TMP

    sed -i 's/\t//g' $IP_BLACKLIST_TMP
    sort -u $IP_BLACKLIST_TMP | tee $IP_BLACKLIST

    rm $IP_TMP
    rm $IP_BLACKLIST_TMP

    wc -l $IP_BLACKLIST

    if hash ipset 2>/dev/null
    then
    ipset flush bloxlist
    while IFS= read -r ip
    do
    ipset add bloxlist $ip
    done < $IP_BLACKLIST
    else
    echo -e '\nipset not found\n'
    echo -e "\nYour bloxlist file is: $IP_BLACKLIST\n"
    fi


    Download here:
        bad_traffic.pl
        bloxlist.sh


    Tags: , , , , , , , , , ,
    Permalink: 20140713.simple.protection.with.iptables.ipset.and.blacklilsts