Fail2ban + fail2sql + Ban Hammer + PHP7

width=625

I recently revisited a project from some time ago that I found and modified the code to support PHP7 which dropped support for mysql extension in favor of mysqli.

If you’re interested, I’ll attach the zip file https://github.com/rjkreider/banhammer.   I mainly just hacked it up and added i to mysql_ functions.  Modified mysql_numrows to mysqli_num_rows and also fixed the constant MYSQL_NUM to MYSQLI_NUM and a few other tweaks in fail2sql.

Note that these are just the ban hammer HTML/PHP files, not fail2sql, so you’ll need to still grab fail2sql and get that setup. I do include fail2sql in my repo with the modified PHP now.

Chrome on Windows 10 Creators Update Hangs

I was plagued with an annoying problem in Chrome 58, beta and Canary for the past month or two. Actually, it dates back to when I was in the Windows Insider Preview for Windows 10 and had already been testing the Windows 10 Creators update. Anyway, Chrome starting ‘hanging’ on me. Meaning, when there should have been a dialog box popup (in most of my experience, this was what was missing), there was nothing. I couldn’t close Chrome, close tabs, etc. I had to hit Escape on the keyboard which would let me click on things, but not actually close the browser.

I decided to search for this issue again on Google to see if anyone had any insight; originally when I searched for this a month or two ago, I wasn’t finding anything useful. All old articles from 2013 etc.

Today was my lucky day. I found a Spiceworks article from April 2017 indicating others had the same problem. I was happy in that it wasn’t just me having the problem! There was a solution to disable Hardware Acceleration (I tried this previously with no luck).  I then saw a comment indicating this was fixed in chromium 60 and could also be worked around by supplying a -disable-dwm-composition flag at Chrome startup.

I grabbed Chrome Canary which is v60 at this time and so far things have been stable!

From Linux Install to WordPress

A typical installation of Debian 8.x (Jessie) precedes this where I only select base system and ssh server options during operating system installation.  After installation, this is a typical configuration to get me up and running. These are my notes.

Debian Customization

These are customizations to suit my taste.

apt-get update && apt-get upgrade
dpkg-reconfigure dash
echo UseDNS no >>/etc/ssh/sshd_config && /etc/init.d/ssh restart
apt-get install fail2ban vim-nox unzip

Webserver Installation: nginx

wget http://nginx.org/keys/nginx_signing.key
apt-key add nginx_signing.key
echo 'deb http://nginx.org/packages/debian/ jessie nginx' >> /etc/apt/sources.list
echo 'deb-src http://nginx.org/packages/debian/ jessie nginx' >> /etc/apt/sources.list
apt-get update && apt-get install nginx

nginx Configuration

There are a few customizations I make and I have scripted most of this since it’s repetitive.

In the first line below, worker_processes 2; is derived from grep 'cpu cores' /proc/cpuinfo | head -1
sed -i 's/user[ ]*nginx/user www-data/g; s/worker_processes[ ]*1/worker_processes 2/g' /etc/nginx/nginx.conf
sed -i 's/access_log.*;/access_log off;/g' /etc/nginx/nginx.conf
sed -i '/access_log off;/a client_max_body_size 12m;' /etc/nginx/nginx.conf
/etc/init.d/nginx restart

With basic configuration changes made to nginx.conf, I now focus on creating the site configuration.

rm /etc/nginx/conf.d/*

cat <<EOF >>/etc/nginx/conf.d/`hostname`.conf
server {
        listen 80;
        root /var/www;
        index index.php index.html index.htm;

        server_name techish.net www.techish.net;

        location / {
                try_files $uri $uri/ /index.php;
        }

        location ~ .php$ {
                try_files $uri =404;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name
;
                include fastcgi_params;
                fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        }

    location ~ /.well-known {
                allow all;
        }
}
EOF

That concludes nginx installation and configuration to THIS point. I’ll revisit toward the end when I implement SSL.

PHP 7 Installation

I use dotdeb to install PHP 7.0 via apt-get.

echo 'deb http://packages.dotdeb.org jessie all' >> /etc/apt/sources.list
echo 'deb-src http://packages.dotdeb.org jessie all' >> /etc/apt/sources.list
wget https://www.dotdeb.org/dotdeb.gpg
apt-key add dotdeb.gpg
apt-get update
apt-get install php7.0-fpm php7.0-mysql php7.0-gd php7.0-mcrypt

PHP 7 Configuration

With PHP7 installation completed, I make a few changes.

sed -i 's/^upload_max_filesize.*/upload_max_filesize = 10m/g; s/^allow_url_fopen.*/allow_url_fopen = Off/g; s/^post_max_size.*/post_max_size = 12m/g' /etc/php/7.0/fpm/php.ini

MySQL (MariaDB) Installation

Installing MariaDB is pretty straight forward with only a minor tweak in the configuration at the end.

apt-get install mariadb-server

MariaDB Configuration

sed -i 's/^bind-address/#bind-address/g; /^#bind-address/a skip-networking' /etc/mysql/my.cnf
mysql_secure_installation

Restart Services & Test

Restart the services and test out things to make sure everything works.

systemctl restart nginx.service
systemctl restart php7-fpm.service
systemctl restart mysql.service

WordPress Installation

WordPress installation is straight forward.

Database Preparation

Make sure to substitute wordpress, wpuser and ... below to reflect your database, database username and database user password.
cd /var/www
mysql -uroot -p -e create database wordpress; grant all on wordpress.* to 'wpuser'@'%' identified by '...'; flush privileges

WordPress Download & Extract

wget https://wordpress.org/latest.zip
unzip latest.zip
mv wordpress/* .
rm -rf wordpress/; rm latest.zip
chown www-data.www-data -R .

WordPress Configuration

At this point, the database is ready to go and I just visit my website to finish the WordPress installation via Web interface.

Let’s Encrypt SSL Certificate

Installation

openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Add Jessie backports repo and install.

echo 'deb http://ftp.debian.org/debian jessie-backports main' >>/etc/apt/sources.list
apt-get update
apt-get install certbot -t jessie-backports

Certificate Generation

I generate a certificate for my top level domain and subdomain.

certbot certonly --webroot -w /var/www -d techish.net
certbot certonly --webroot -w /var/www -d www.techish.net

nginx SSL Configuration

Create a directory in /etc/nginx to store a few snippets of nginx configuration.

mkdir /etc/nginx/ssl

Create SSL parameters configuration file, ssl-params.conf, that we’ll call in our site configuration file.

cat <<EOF >>/etc/nginx/ssl/ssl-params.conf
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
    ssl_ecdh_curve secp384r1;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;
    add_header Strict-Transport-Security max-age=63072000; includeSubdomains; preload;
    add_header Strict-Transport-Security max-age=63072000; includeSubdomains;
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
EOF

Create a configuration file, ssl-kreider.conf, that will reference where my top level domain SSL certificate is stored. I call this file from main nginx site configuration file later.

cat <<EOF >>/etc/nginx/ssl/ssl-kreider.conf
ssl_certificate /etc/letsencrypt/live/techish.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/techish.net/privkey.pem;
EOF

Create a configuration file, ssl-www-kreider.conf, that will reference where my www subdomain SSL certificate is stored. I call this file from main nginx site configuration file later.

cat <<EOF >>/etc/nginx/ssl/ssl-www-kreider.conf
ssl_certificate /etc/letsencrypt/live/www.techish.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.techish.net/privkey.pem;
EOF

I update my main site’s nginx configuration.

Note that `hostname` will expand the system hostname automatically. Replace `hostname`.conf (including backticks) with your configuration file name as applicable.
vim /etc/nginx/conf.d/`hostname`.conf

My finalized site configuration file.

server {
        listen 80;
        server_name techish.net www.techish.net;
        return 307 https://techish.net$request_uri;
}

server {
        listen 443 ssl;
        include ssl/ssl-kreider.conf;
        include ssl/ssl-params.conf;
        root /var/www;
        index index.php index.html index.htm;

        server_name techish.net;

        location / {
                try_files $uri $uri/ /index.php;
        }

        location ~ .php$ {
                try_files $uri =404;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name                                                                                                                               ;
                include fastcgi_params;
                fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        }
}

Powershell logparse regexp to csv

Input line:

Thu 2017-03-30 00:00:07: user@domain.com (John Doe) checked mail from 127.0.0.1 using IMAP, 0 msgs collected, 21 remaining

Powershell script:

$rxp = "([a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)|(d{1,3}.d{1,3}.d{1,3}.d{1,3})|(POP|IMAP)|(^[A-Z][a-z]+sd{4}-d{2}-d{2}sd{2}:d{2}:d{2})"

gc ".*.log" | select-string -pattern $rxp -allmatches | foreach {

if ($_.Matches.count -ne 4) {
return
}
[pscustomobject]@{
 'date'=$_.Matches[0]
 'email'=$_.Matches[1]
 'ipaddr'=$_.Matches[2]
 'proto'=$_.Matches[3]
 }
} | export-csv -notype analysis.csv