fighting the lack of good ideas

4 places to check your website’s ssl/tls security settings

Qualys –

High-Tech Bridge –

Comodo –

SSL Checker –

ssl configuration for apache 2.4 on centos 7 with let’s encrypt

In follow-up to previous posts I’ve had about SSL (specifically with Let’s Encrypt), here is the set of SSL configurations I use with all my sites. These, if used correctly, should score you an “A+” with no warnings from Note: I have an improved entropy package installed (twuewand). This is adapted from the Mozilla config generator with specific options added for individual sites and/or to match Let’s Encrypt’s recommendations.

Please note: you will need to modify the config files to represent your own domains, if you choose to use these as models.


#SSL options for all sites
Listen 443
SSLPassPhraseDialog  builtin
SSLSessionCache         shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout  300
Mutex sysvsem default
SSLRandomSeed startup builtin
SSLRandomSeed startup file:/dev/urandom  1024
# requires twuewand to be installed
SSLRandomSeed startup exec:/bin/twuewand 64
SSLRandomSeed connect builtin
SSLRandomSeed connect file:/dev/urandom 1024
SSLCryptoDevice builtin
# the SSLSessionTickets directive should work - but on Apache 2.4.6-45, it does not
#SSLSessionTickets       off
SSLCompression          off
SSLHonorCipherOrder	on
# there may be an unusual use case for enabling TLS v1.1 or 1 - but I don't know what that would be
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLOptions +StrictRequire
SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache        shmcb:/var/run/ocsp(128000)

#all unknown requests get domain.tld (over http)
<VirtualHost *:80>
    DocumentRoot /var/html
    ServerName domain.tld
    ServerAlias domain.tld *.domain.tld
    ErrorLog logs/domain-error_log
    CustomLog logs/domain-access_log combined
    ServerAdmin user@domain.tld
    <Directory "/var/html">
         Options All +Indexes +FollowSymLinks
         AllowOverride All
         Order allow,deny
         Allow from all

SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript text/css text/php


<Virtualhost *:80>
    ServerName domain.tld
# could use * instead of www if you don't use subdomains for anything special/separate
    ServerAlias domain.tld www.domain.tld
    Redirect permanent / https://domain.tld/

<VirtualHost *:443>
    SSLCertificateFile /etc/letsencrypt/live/domain.tld/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/domain.tld/privkey.pem
# if you put "fullchain.pem" here, you will get an error from ssllabs
    SSLCertificateChainFile /etc/letsencrypt/live/domain.tld/chain.pem
    DocumentRoot /var/www/domain
    ServerName domain.tld
    ErrorLog logs/domain-error_log
    CustomLog logs/domain-access_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
    ServerAdmin user@domain.tld

# could put this in defaults.conf - I prefer it in each site config
    SSLEngine on

<Files ~ "\.(cgi|shtml|phtml|php3?)$">
    SSLOptions +StdEnvVars
<Directory "/var/www/cgi-bin">
    SSLOptions +StdEnvVars

SetEnvIf User-Agent ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

    <Directory "/var/www/domain">
         Options All +Indexes +FollowSymLinks
         AllowOverride All
         Order allow,deny
         Allow from all


I use the z....conf formatting to ensure all site-specific configs are loaded after everything else. That conveniently breaks every site into its own config file, too.

The config file for a non-https site is much simpler:

<VirtualHost *:80>
    DocumentRoot /var/www/domain
    ServerName domain.tld
    ServerAlias domain.tld *.domain.tld
    ErrorLog logs/domain-error_log
    CustomLog logs/domain-access_log combined
    ServerAdmin user@domain.tld
    <Directory "/var/www/domain">
         Options All +Indexes +FollowSymLinks
         AllowOverride All
         Order allow,deny
         Allow from all

If you’re running something like Nextcloud, you may want to turn on Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains" in the <VirtualHost&gt directive for the site. I haven’t decided yet if I should put this in every SSL-enabled site’s configs or not.

automated let’s encrypt ssl certificate renewal on centos 7

In my how-to for Let’s Encrypt, I gave an example script that can be called via cron (or manually) which will renew Let’s Encrypt SSL certificates under CentOS 6.

If you want to do it on CentOS 7 (which is what I am now running), use the following:

cd ~/letsencrypt
git pull
systemctl stop httpd.service
~/letsencrypt/letsencrypt-auto --agree-tos --keep --rsa-key-size 2048 --standalone certonly -m user@domain.tld -d domain.tld [-d sub.domain.tld [-d ...]]
systemctl start httpd.service

Now, what does this script do? Step by step:

  1. clear-out the last grab of the Let’s Encrypt git repo (there’s probably a better way to do this, but I don’t know what it is)
  2. go to root’s home (/root)
  3. clone-down the Let’s Encrypt toolset
  4. stop httpd (Apache in my case, though you might be running nginx or something else
  5. run the cert tool in automated form:
    1. agree to terms of service
    2. keep current cert if it doesn’t need to be updated
    3. key size of 2048 bits
    4. run the standalone webserver to verify “ownership” of the domain
    5. generate just the cert
    6. administrative email (optional, but “encouraged”)
    7. domain(s) to issue cert for (must be individually identified with successive -d flags; LE does not support wildcard certs)
  6. restart httpd

I set mine to run @weekly in cron@monthly is likely good enough, but since it’s “free” to run, running slightly more than is necessary seems good to me. Plus, if you’re getting SSL certs for many domains all being served from the same server, they may have different expiration dates, so running more often is better.

My crontab entry for renewing certs:

@weekly /root/

let’s encrypt centos 6 – truly free ssl

There’s been quite a bit of excitement surrounding Let’s Encrypt recently – a truly 100% free SSL issuer.

Last week I helped a friend of mine get his first Let’s Encrypt certificate generated and configured for his website. One of the things I found incredibly frustrating is that Let’s Encrypt does not have a package for Red Hat/CentOS/Fedora! Ignoring such a massive installed base seems monumentally dumb – so I hope that they correct it soon. Until they do, however, here’s a tutorial that should cover the gotchas for getting Let’s Encrypt to work on a CentOS 6 server with Apache 2.

The documentation (as of 06 Jan 2015) on the Let’s Encrypt website is in error in a few places (or, at least, not as correct as is could/should be). One big thing to note, for example, is that it says Python 2.6 is supported (the current release for RHEL/CentOS 6). If you run the certificate generator without the --debug flag, though, it will error-out saying Python 2.6 is not supported.

While I used an existing CentOS 6 server, I’ll start this tutorial as I have many others – by telling you to go get a CentOS 6 server from Digital Ocean or Chunk Host.


Login as root (or a sudo-privileged account – but root is easier), and install Apache, Python, and SSLyum install httpd python mod_ssl.

Also enable the EPEL repository: yum install epel-repository (available from the CentOS Extras repository. I’m going to assume you are familiar with configuring Apache, and will only provide the relevant snippets from ssl.conf herein.

Now that the basics are done, let’s move to Let’s Encrypt. I ran the tool in interactive mode (which is going to require ncurses to be available – it’s probably already installed on your system) – but you’ll want to add a crontab entry since Let’s Encrypt certs expire after 90 days, so I’ll compact the interactive session into a single command-line call at the end, which you’ll need to “know” how to do, since the --help argument doesn’t do anything yet (that I could find).

Initial Certificate Creation

First, grab the latest Let’s Encrypt from GitHub:
git clone && cd letsencrypt

Stop Apache: service httpd stop. Let’s Encrypt is going to try to bind to ports 80 and 443 to ensure you have control the domain.

Now run the letsencrypt-auto tool – in debug mode so it’ll work with Python 2.6: ./letsencrypt-auto --debug certonly.

Use certonly because the plugins to automate installing for Apache and Nginx don’t work on CentOS yet.

Enter your domain name(s) for which you want to issue a certificate. If you accept incoming connections to www.domain.tld and domain.tld, be sure to put both in the list (likewise, if you have, say, blog.domain.tld that you want included).

Enter an administrative email address.

When the tool finishes, it’ll put symlinks in /etc/letsencrypt/live/domain.tld, with the “actual” certs in /etc/letsencrypt/archive/domain.tld. We’re going to reference the symlinks in /etc/letsencrypt/live/domain.tld next.

Edit /etc/httpd/conf.d/ssl.conf (I prefer emacs – but use whatever you prefer), and add the following lines in your VirtualHost directive:
SSLCertificateFile /etc/letsencrypt/live/domain.tld/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domain.tld/privkey.pem
SSLCACertificateFile /etc/letsencrypt/live/domain.tld/cert.pem

Restart Apacheservice httpd start.

Try hitting https://domain.tld in your web browser – and you should be golden!

Automating Renewal

Create a small shell script called somewhere you’ll remember where it is – like /root:
service httpd stop
# add additional '-d' entries for more subdomains
/path/to/letsencrypt/letsencrypt-auto --debug --keep --agree-tos --rsa-key-size 2048 certonly -m ssladmin@domain.tld -d domain.tld -d www.domain.tld
service httpd start

For your crontab entry, do the following to setup monthly cert renewal:
@monthly /path/to/

determining the ‘legitimacy’/’reliability’ of a domain

I’ve recently been asked by several people to investigate websites (especially e-commerce ones) for reliability/legitimateness.

Thought someone else may find my process useful, and/or have some ideas on how to improve it ?

So here goes:

  1. Pop a terminal window (I’m on a Mac, so I open Terminal – feel free to use your terminal emulator of choice (on Windows, you’ll need to have the Subsystem for Linux or Cygwin installed))
    1. Type whois <domain.tld> | less
    2. Look at all of the following:
      • Creation (Creation Date: 2006-02-22T01:12:10Z)
      • Expiration (Registry Expiry Date: 2023-02-22T01:12:10Z)
      • Name server(s) (NS3.PAIRNIC.COM)
      • Registral URL (
      • Registrar (Pair Domains)
      • Contact info (should [generally] be anonymized in some manner)
    3. Possible flags:
      • If the domain’s under 2 years old, and/or the registration period is less than a year (we can talk about when short registrations may make sense in the comments)
      • If the name servers are “out of the country” (which, of course, will vary based on where you are)
      • If the contact info isn’t anonymized
  2. Load the website in question in a browser (use an ingonito and/or proxied tab, if you like) and review the following types of pages:
    • Contact Us
      • Where are they located?
      • Does the location stated match what you expect based on the whois response?
    • About Us
      • Does it read “naturally” in the language it purports to be written in?
        • Ie, does it sound like a native speaker wrote it, or does it sound stiltedly/mechanically translated?
    • Does it match what is in the whois record and the Contact Us page?
    • Do they provide social media links (Twitter, Facebook, LinkedIn, Instagram, etc)?
      • What do their social media presence(s) say about them?
    • Return/Refund Policy (for ecommerce sites only)
      • What is the return window?
      • How much will be charged to send it back and/or restorck it?
    • Shipping Policy (for ecommerce sites only)
      • How long from submitting an order to when it ships to when it arrives?
      • Where is it shipping from?
    • Privacy Policy (only applies if you may be sharing data with them (ecommerce, creating accounts, etc)
      • What do they claim they will (and will not) do with your private information?
  3. Is the site running over TLS/SSL?
    • You should see a little padlock icon in your browser’s address bar
    • Click that icon, and read what the browser reports about the SSL certificate used
    • Given that running over TLS is 100% free, there is absolutely NO reason for a site to NOT use SSL (double especially if they’re purporting to be an ecommerce site)

Reviewing these items usually takes me about 2-3 minutes.

It’s not foolproof (after all, better fools are invented every day), but it can give you a good overview and relative confidence level in the site in question.

sshuttle – a simple transparent proxy vpn over ssh

I found out about sshuttle from a random tweet that happened to catch my eye.

Here’s the skinny (from the readme):

  • Your client machine (or router) is Linux, FreeBSD, or MacOS.
  • You have access to a remote network via ssh.
  • You don’t necessarily have admin access on the remote network.
  • The remote network has no VPN, or only stupid/complex VPN protocols (IPsec, PPTP, etc). Or maybe you are the admin and you just got frustrated with the awful state of VPN tools.
  • You don’t want to create an ssh port forward for every single host/port on the remote network.
  • You hate openssh’s port forwarding because it’s randomly slow and/or stupid.
  • You can’t use openssh’s PermitTunnel feature because it’s disabled by default on openssh servers; plus it does TCP-over-TCP, which has terrible performance.

Here’s how I set it up on my Mac

Install homebrew:

/bin/bash -c "$(curl -fsSL"

Install sshuttle (as a regular user):

brew install sshuttle

Test the connection to a server you have:

sudo sshuttle -r <user>@host.tld -x host.tld 0/0 -vv

I also made sure that my target server could be connected-to via certificate for my local root user – but you can use a password if you prefer.

Check your IP address:


Once you make sure the connection works, Ctrl-C to end the session.

Then setup an alias in your shell’s .profile (for me, it’s .bash_profile):

alias vpn='sudo sshuttle -r <user>@domain.tld -x domain.tld 0/0'

Other things you can do

According to the full docs, there are a lot more things you can do with sshuttle – including running it on your router, thereby VPN’ing your whole LAN through an endpoint! You can also run it in server mode.

This is a super useful little utility!

basic dockerized jitsi deployment with an apache reverse proxy on centos

After a friend of mine told me he wanted to deploy Jitsi on my main webserver, and me saying “sure”, I decided I wanted to get it up and running on a new server both so I knew how to do it, and to avoid the latency issues of videoconferencing from central North America to Germany and back.

Before I go into how I got it working, let me say that the official Quick Start guide is good – but it doesn’t cover anything but itself.

Here’s the basic setup:

What To Do:

Once you have your new CentOS instance up and running (I used Vultr), here’s everything you need to install:

yum -y install epel-release && yum -y upgrade && yum -y install httpd docker docker-compose screen bind-utils certbot git haveged net-tools mod_ssl

I also installed a few other things, but that’s because I’m multi-purposing this server for Squid, and other things, too.

Enable Apache, firewalld, & Docker:

systemctl enable httpd && systemctl enable docker && systemctl enable firewalld

Now get your swap space setup:

fallocate -l 4G /swapfile && chmod 0600 /swapfile && mkswap /swapfile && swapon /swapfile

Add the following line to the bottom of your /etc/fstab:

/swapfile swap swap default 0 0

Restart your VPS:

shutdown -r now

Get your cert from Let’s Encrypt (make sure you’ve already setup appropriate CAA & A records for your domain and any subdomains you want to use):

certbot -t -n --agree-tos --keep --expand --standalone certonly --must-staple --rsa-key-size 4096 --preferred-challenges dns-01,http-01 -m <user>@<domain.tld> -d <jitsi.yourdomain.tld>

Create a root crontab entry to run certbot frequently (I do @weekly ~/

Go to the home directory of whatever user you plan to run Jitsi as:

su - <jitsi-user>

Begin the Quick Start directions:

  • git clone && cd docker-jitsi-meet
  • mv env.example .env
  • Change the timezone in .env from Europe/Amsterdam if you want it to show up in a sane timezone (like Etc/UTC)
  • mkdir -p ~/.jitsi-meet-cfg/{web/letsencrypt,transcripts,prosody,jicofo,jvb}
  • docker-compose up -d

Now configure Apache for SSL. Start with this reference I posted.

But in the [sub]domain-specific conf file z-[sub]domain-tld.conf, add proxy and authentication lines (so that only people you allow to use your video conference can actually use it):

ProxyPreserveHost on
ProxyPass / http://localhost:8000/ nocanon
ProxyPassReverse / http://localhost:8000/
ProxyRequests       off
AllowEncodedSlashes NoDecode
<Proxy http://localhost:8000/*>
    Order deny,allow
    Allow from all
    Authtype Basic
    Authname "Password Required"
    AuthUserFile /etc/httpd/.htpasswd
    Require valid-user
RewriteEngine       on
RewriteRule        ^/meetwith/(.*)$ http://%{HTTP_HOST}/$1 [P]
ProxyPassReverseCookiePath /meetwith /

Reload your configs, and make sure they’re happy, fixing any errors that may exist:

apachectl graceful

Setup at least one user who’ll be able to access the site:

htpasswd -B -c /etc/httpd/.htpasswd <user>

You should also configure firewalld to allow only what you want (http, https, ssh):

firewall-cmd --zone=public --add-service=http && firewall-cmd --zone=public --add-service=https && firewall-cmd --zone=public --add-service=ssh

With any luck, when you now navigate to https://[sub.]domain.tld in your web browser, and enter your username and password you created with htpasswd, you’ll get the Jitsi welcome page!

Other Resources: