Docker stubby, run on start systemd; Raspbian

Hi,

Lets get the first question out of the way, why run stubby in a container:  I was hoping I wouldn’t have to compile from source (https://github.com/getdnsapi/getdns),  but stubby isn’t in stable Debian or Raspbian repositories; although buster works fine with Debian (x86), this is not the case with Raspbian (arm) had issues with dhcpd & iptables,  there are probably more issues, but I went back to stable before investigating further. The docker image compiles the source,  but the build environment is predefined; so this is a good compromise for me.

The second question: Why use systemd to start the container,  I like systemd and understand it; I don’t think any other reasons are required?

Setup

Install docker:

https://docs.docker.com/install/linux/docker-ce/debian/

sudo apt-get install git

git clone https://github.com/juzam/docker-getdns-stubby.git

cd ~/docker-getdns-stubby

The Dockerfile,  pulls the development branch (which on 29/11/18, wouldn’t compile);  Fixed by the developer 30/11/18, so we just need to change the exposed port:

mv Dockerfile Dockerfile.bak

nano or vi  Dockerfile

FROM debian:buster
MAINTAINER "Giovanni Angoli <[email protected]>"

RUN apt-get update && apt-get install -y libyaml-dev libssl-dev libtool-bin autoconf git make && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

RUN git clone https://github.com/getdnsapi/getdns.git

WORKDIR getdns

RUN git checkout develop && git submodule update --init && libtoolize -ci && autoreconf -fi && mkdir build
WORKDIR build
RUN ../configure --without-libidn --without-libidn2 --enable-stub-only --with-stubby && make && make install && ldconfig

COPY stubby.yml /usr/local/etc/stubby/stubby.yml

EXPOSE 53

CMD [ "/usr/local/bin/stubby" ]

If you wish to use to stubby with with pihole, then change EXPOSE to:

EXPOSE 5353

The stubby.yml provided this git repository uses IPv6, so needs updating if like myself using IPv4:

mv stubby.yml stubby.yml.bak

nano or vi stubby.yml

resolution_type: GETDNS_RESOLUTION_STUB
dns_transport_list:
  - GETDNS_TRANSPORT_TLS

tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
tls_query_padding_blocksize: 256

edns_client_subnet_private: 1
idle_timeout: 10000
round_robin_upstreams: 0

listen_addresses:
  - 127.0.0.1@53
upstream_recursive_servers:
  - address_data: 9.9.9.9
    tls_auth_name: "dns.quad9.net"

If you wish to use to stubby with with pihole, I advise updating listen_addresses; as follows:

listen_addresses: 
  - 127.0.2.2@5353

sudo docker build -t getdns-stubby .

Systemd

nano or vi /lib/systemd/system/docker-stubby.service

[Unit]
Description=Stubby Container
After=docker.service

[Service]
RemainAfterExit=yes
ExecStart=/usr/bin/docker run -it -d --net=host getdns-stubby
ExecStop=/home/pi/stop-stubby.sh
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

nano or vi /home/pi/stop-stubby.sh

#!/bin/bash
/usr/bin/docker ps -q --filter ancestor=getdns-stubby | xargs -r docker stop

systemctl daemon-reload

systemctl enable docker-stubby

systemctl start docker-stubby

Testing

sudo apt-get install dnsutils

dig @127.0.0.1 quad9.net

expected result:

; <<>> DiG 9.10.3-P4-Raspbian <<>> @127.0.0.1 quad9.net
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 51250
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65535
;; QUESTION SECTION:
;quad9.net. IN A

;; ANSWER SECTION:
quad9.net. 1200 IN A 216.21.3.77

;; Query time: 174 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Nov 21 00:03:58 UTC 2018
;; MSG SIZE rcvd: 63

If result is  different, please check the above instructions.

Now what?

You could now use the host which you have setup as a dns resolver, but I suggest going beyond that and use pihole:

https://pi-hole.net/

with stubby:

https://blog.sandchaschte.ch/en/pi-hole-with-dns-over-tls

Updating Stubby:

Every time docker-stubby. is started (including restarts), a new container is created, so when updating a clean up seems like a good idea; please follow the instructions below:

if using pihole:

# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.0.1

I suggest adding another nameserver temporarily, for example quad9:

nano or vi /etc/resolv.conf

nameserver 9.9.9.9

If docker-stubby. is the only docker on the host, then:

sudo systemctl stop docker-stubby.service
sudo docker system prune (and y)
sudo docker image rm getdns-stubby
cd ~/docker-getdns-stubby
sudo docker build -t getdns-stubby .
sudo systemctl start docker-stubby.service

if not:

sudo systemctl stop docker-stubby
docker ps -a
remove all containers for getdns-stubby with sudo docker rm for example:
sudo docker rm bf3aa2dd8bb1
sudo docker image rm getdns-stubby
cd ~/docker-getdns-stubby
sudo docker build -t getdns-stubby .
sudo systemctl start docker-stubby.service

Thanks Tom.

P.S Please feel free to comment.

Sources:

https://github.com/juzam/docker-getdns-stubby
https://blog.sandchaschte.ch/en/pi-hole-with-dns-over-tls
https://pi-hole.net/
https://github.com/getdnsapi/getdns.git
https://docs.docker.com/install/

WordPress Hardening

Hi,

This is for people with there own server running cpanel/apache. People using shared hosting, their provider will probably enable this if asked.

First make sure mod_security & mod_security2-mlogc are enabled, this can done via easy apache 4.

Install and enable OWASP ModSecurity Core Rule Set V3.0 rules under Select ModSecurity™ Vendors. ModSecurity™ Configuration:

  • Audit Log Level
  • Connections Engine set to Process the rules
  • Rules Engine set to Process the rule

Install CMC:

https://www.configserver.com/cp/cmc.html

/etc/apache2/conf.d/modsec/modsec2.user.conf:

#Wordpress bruteforce
SecAction phase:1,nolog,pass,initcol:ip=%{REMOTE_ADDR},initcol:user=%{REMOTE_ADDR},id:5000134
<Locationmatch "/wp-login.php">
# Setup brute force detection.
# React if block flag has been set.
SecRule user:bf_block "@gt 0" "deny,status:401,log,id:5000135,msg:'ip address blocked for 5 minutes, more than 10 login attempts in 3 minutes.'"
# Setup Tracking. On a successful login, a 302 redirect is performed, a 200 indicates login failed.
SecRule RESPONSE_STATUS "^302" "phase:5,t:none,nolog,pass,setvar:ip.bf_counter=0,id:5000136"
SecRule RESPONSE_STATUS "^200" "phase:5,chain,t:none,nolog,pass,setvar:ip.bf_counter=+1,deprecatevar:ip.bf_counter=1/180,id:5000137"
SecRule ip:bf_counter "@gt 10" "t:none,setvar:user.bf_block=1,expirevar:user.bf_block=300,setvar:ip.bf_counter=0"
</locationmatch> 
#BadBots
SecRule REQUEST_HEADERS:User-Agent "@pmFromFile /etc/apache2/conf.d/modsec/badbotlist.txt" "id:980001,rev:1,severity:2,log,msg:'Bot Rule: Black Bot detected.'"
#Prevent DDOS to xmlrpc.php (wordpress) with ModSecurity
SecAction "phase:1,id:400000,t:none,pass,nolog,initcol:global=global,initcol:ip=%{remote_addr}"
SecRule REQUEST_URI "/xmlrpc\.php" "id:400001,nolog,drop,chain,phase:1,setvar:ip.ddos=+1,deprecatevar:ip.ddos=2/60,expirevar:ip.ddos=120"
SecRule IP:DDOS "@gt 5" "nolog"

systemctl restart httpd

.htaccess (Shared hosting users can do this without contacting their hosting provider):

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress
# Block WordPress xmlrpc.php requests
<Files xmlrpc.php>
order deny,allow
deny from all
allow from your.public.i.p
</Files>
<files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</files>
<files wp-config.php>
order allow,deny
deny from all
</files>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>

# disable directory browsing
Options All -Indexes

Thanks Tom

P.S Please feel free to comment.

Sources:

https://wpprofix.com/stopped-wordpress-brute-force-attacks-server/
https://www.hostinger.co.uk/tutorials/xmlrpc-wordpress
https://forums.cpanel.net/threads/wp-login-php-and-mod-security.430242/page-2
https://malware.expert/prevent-ddos-xmlrpc-php-wordpress-modsecurity/
https://www.cloudways.com/blog/protect-wordpress-with-htaccess/

Advanced Policy Firewall Systemd

Hi and welcome to my first blog post, this blog won’t be updated regularly; just when I’ve found a fix or something interesting to post about. Sorry for the look didn’t go much on design, just wanted to get straight to the posting blogs.

For my first blog I’m posting about using apf with systemd, apf is a wrapper for iptables, more details can be found here:

Advanced Policy Firewall

apf is a very good firewall an alternative is csf:

https://configserver.com/cp/csf.html

csf is firewall+, whereas apf approach is do one job and do that job well. A great tool when combined with fail2ban and mod-security rules. All of these are great tools when you manage quite a few Apache webservers, saves on configuring a ton of iptables rules for each server.

My only issue with apf is that it is started with an init.d script, that just reports OK doesn’t advise whether iptables has actaully started or not. But if we create a systemd unit file instead:

/lib/systemd/system/apf.service

[Unit]
Description=apf firewall with iptables
After=syslog.target network.target

[Service]
RemainAfterExit=yes
ExecStart=/usr/local/sbin/apf --start
ExecStop=/usr/local/sbin/apf --stop
Restart=on-failure
RestartSec=5

[Install]
WantedBy=basic.target

systemctl daemon-reload

systemctl enable apf

systemctl start apf.

Now if we issue:

systemctl status apf

We can clearly see now if iptables has initialized or not.  I was hoping to find a way to get apf to fail if iptables has any issues, but was unable to work this out on centos 7. If anyone has any thoughts on this please comment.

I hope somebody find this of use, all comments are welcome.

Thanks Tom.