diff --git a/server-php/README.md b/server-php/README.md index a20b324..f62c418 100644 --- a/server-php/README.md +++ b/server-php/README.md @@ -15,14 +15,14 @@ You can set the size you want for the cache. Here, we chose 256MB to store 64,000 records at the most. -The cache is enabled by default, but you can turn it off by setting the variable `$use_cache` to false in `api.php`. +The cache is enabled by default, but you can turn it off by setting the variable `$use_cache` to false in `config.php`. 6. Create the RSA private key (PEM format) to sign the server's answers: `openssl genrsa -out private_key 4096`. 7. Create the associated public key for the clients to check the server's signature: `openssl rsa -in private_key -pubout -out public_key`. 8. Store your private key **outside the web server folder**, and put the public key accessible from the web at `download/public_key`. -9. Edit `api.php` with the right path to your private key (replace `/path/to/your/private/key`). -10. Edit `api.php` with the **uppercase** SHA256 fingerprint of your HTTPS certificate (replace `SHA256_FINGERPRINT_OF_YOUR_SERVER_S_HTTPS_CERTIFICATE` in `$response->cmh_sha256`). You can use this command to retrieve the SHA256 fingerprint: ` openssl x509 -in your_certificate.crt -inform PEM -out /dev/stdout -outform DER | sha256sum | tr a-z A-Z` -11. Edit `api.php` and replace `['checkmyhttps.net','www.checkmyhttps.net','185.235.207.57']` with all your server's FQDN and ip addresses. +9. Edit `config.php` with the right path to your private key (replace `/path/to/your/private/key`). +10. Edit `config.php` with the **uppercase** SHA256 fingerprint of your HTTPS certificate (replace `SHA256_FINGERPRINT_OF_YOUR_SERVER_S_HTTPS_CERTIFICATE` in `$response->cmh_sha256`). You can use this command to retrieve the SHA256 fingerprint: ` openssl x509 -in your_certificate.crt -inform PEM -out /dev/stdout -outform DER | sha256sum | tr a-z A-Z` +11. Edit `config.php` and replace `['checkmyhttps.net','www.checkmyhttps.net','185.235.207.57']` with all your server's FQDN and ip addresses. ### Installation @@ -30,6 +30,43 @@ The cache is enabled by default, but you can turn it off by setting the variable 2. Install dependencies with composer: `composer install` inside your webroot (else you can extract `vendor-static.tar.gz`). 3. Then configure your clients to use your own check server. +### Scripted installation +1. Prepare the directory layout +- sources +``` +$HOME/checkmyhttps +``` +- wwwdir +``` +/opt/checkmyhttps/www +``` +- private key dir +``` +/opt/checkmyhttps/key +``` +- tmpdir +``` +/opt/checkmyhttps/tmp +``` +- locate the server's https certificate +``` +/etc/ssl/my.crt +``` +- locate the webserver or php user +``` +www-data +``` + +2. installation +``` +# add this line in `/etc/fstab`: +tmpfs /opt/checkmyhttps/tmp tmpfs mand,noatime,size=256m,nosuid,noexec,uid=www-data,gid=www-data,mode=770 0 0 +mount /opt/checkmyhttps/tmp + +./install.sh /opt/checkmyhttps/www /opt/checkmyhttps/key /etc/ssl/my.crt mydomain.com +``` +3. You will be asked to generate a new app ssl certificate + ### Testing with Docker 1. Put your certificate in `confs/cert` folder (with names: `cert.cer`, `privkey.key` and `chain.cer`). diff --git a/server-php/install.sh b/server-php/install.sh new file mode 100755 index 0000000..ae98fa3 --- /dev/null +++ b/server-php/install.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +BASE=$(readlink -f $(dirname $0)) +IN="$BASE" + +if [ $# -lt 4 ]; then + echo "Usage: $0 []" + exit 3 +fi +OUT="$1" +KEYDIR="$2" +CRT="$3" +THOSTS="$4" +TMPDIR="$5" + + +set -e + +( [ -d $OUT ] && [ -f $CRT ] && [ -d "$KEYDIR" ]) || { + echo "missing directories" + exit 2 +} +( [ ! -f "$KEYDIR/private_key" ] ) && { + echo "private key not found. Create a new one ?" + read A + if [[ "$A" =~ y|Y ]]; then + openssl genrsa -out $KEYDIR/private_key 4096 + openssl rsa -in $KEYDIR/private_key -pubout -out $KEYDIR/public_key + echo "generated server key. Pulic key" + cat $KEYDIR/public_key + fi +} + +( [ -f "$KEYDIR/private_key" ] && [ -f "$KEYDIR/public_key" ]) || { + echo "Key not found" + exit 2 +} + +set +x + +rsync -av --delete $IN/www/ $OUT/ + +ln -sTf $KEYDIR/public_key $OUT/download/public_key + +echo "Config" +CERT_SHA=`openssl x509 -in $CRT -inform PEM -out /dev/stdout -outform DER | sha256sum | tr a-z A-Z | cut -d ' ' -f 1` +sed 's/SHA256_FINGERPRINT_OF_YOUR_SERVER_S_HTTPS_CERTIFICATE/'$CERT_SHA'/' -i $OUT/config.php +sed 's#/path/to/your/private/key#'"$KEYDIR"'/private_key#' -i $OUT/config.php +TH=`tr ',' '\n' <<<"$THOSTS" | awk '{ aa = "'"'"'" $0 "'"'"'" ; if (a) { a=a "," aa } else a=aa} END {print "["a"]"}'` +sed -r -i 's#(\$TRUSTED_HOSTS=).*#\1'$TH';#' $OUT/config.php +if [ -n "$TMPDIR" ]; then + sed -i 's#/var/tmp/cmh_cache/#'${TMPDIR%%}/'#' $OUT/config.php +fi + + +( + + cd $OUT; + COM=composer + composer || { + echo "installing composer" + php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" + php composer-setup.php + php -r "unlink('composer-setup.php');" + COM='php composer.phar' + + } + echo "Installing composer deps" + $COM install +) + +echo "All done" diff --git a/server-php/www/api.php b/server-php/www/api.php index 7b95705..9a1b81e 100644 --- a/server-php/www/api.php +++ b/server-php/www/api.php @@ -2,6 +2,8 @@ include __DIR__ . '/vendor/autoload.php'; +include __DIR__ . '/config.php'; + define('INSTANCE_TITLE', 'CheckMyHTTPS API server'); define('VERSION', '1.6.0'); define('SOCKET_TIMEOUT', ini_get('default_socket_timeout')); @@ -9,14 +11,6 @@ header('Content-Type: application/json'); -//Set this variable to false if you don't want to use the cache -$use_cache = true; - -$path_to_cache = "/var/tmp/cmh_cache/"; - -//Max duree of cache (default: 21600 seconds = 6 hours) -$cacheTTL = 21600; - //DNS record found in cache ? $cacheFound = false; $insertInCache = true; @@ -193,7 +187,7 @@ exit(json_encode(hashAndEncrypt((object)['error' => 'UNKNOWN_PORT'], $sign))); // Replace this array with your server's FQDNs and public IP addresses : -if (in_array($service->host, ['checkmyhttps.net','www.checkmyhttps.net','185.235.207.57'])) $service->ip = '127.0.0.1'; +if (in_array($service->host, $TRUSTED_HOSTS)) $service->ip = '127.0.0.1'; if((!$allowPrivateIp) && ($service->ip !== '127.0.0.1') && (!filter_var($service->ip, FILTER_VALIDATE_IP, ['flags' => (FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)]))) { @@ -381,12 +375,13 @@ function objToString($obj, &$str) */ function hashAndEncrypt($response, $sign) { + global $PRIVATE_KEY, $CERT_SHA256; if(!$sign) return $response; - $private_key = file_get_contents("/path/to/your/private/key"); + $private_key = file_get_contents($PRIVATE_KEY); - $response->cmh_sha256 = 'SHA256_FINGERPRINT_OF_YOUR_SERVER_S_HTTPS_CERTIFICATE'; + $response->cmh_sha256 = $CERT_SHA256; $response_to_sign = ""; diff --git a/server-php/www/config.php b/server-php/www/config.php new file mode 100644 index 0000000..2ed2323 --- /dev/null +++ b/server-php/www/config.php @@ -0,0 +1,13 @@ +