diff --git a/Hosting.md b/Hosting.md index de37e803..418bc8a9 100644 --- a/Hosting.md +++ b/Hosting.md @@ -10,7 +10,7 @@ - [OVH VMware](http://www.ovh.ie/vps/vps-cloud.xml) VMware - [HostHatch](https://portal.hosthatch.com/aff.php?aff=250) KVM, storage VPS - [Vultr](http://www.vultr.com/?ref=6815796) hourly, 3+GHz, SSD, storage VPS -- vps.me/Hostinger free, IPv6 only +- [vps.me](http://www.vps.me/order/free-vps) by Hostinger IPv6 only, free ## PaaS diff --git a/debian-setup.sh b/debian-setup.sh index 653bef77..f85199d7 100755 --- a/debian-setup.sh +++ b/debian-setup.sh @@ -1,9 +1,11 @@ #!/bin/bash # -# Debian jessie server setup. +# Debian jessie virtual server setup. # +# AUTHOR :Viktor Szépe +# URL :https://github.com/szepeviktor/debian-server-tools +# LICENSE :The MIT License (MIT) # AUTORUN :wget -O ds.sh http://git.io/vtcLq && . ds.sh -# GIST-AUTORUN :wget -O ds.dh http://git.io/vIlCB && . ds.dh # How to choose VPS provider? # @@ -14,6 +16,8 @@ # - Nightime technical support network or hardware failure response time # - Daytime technical and billing support # - (D)DoS mitigation +# +# See https://github.com/szepeviktor/wordpress-speedtest/blob/master/README.md#results # Packages sources DS_MIRROR="http://http.debian.net/debian" @@ -34,11 +38,6 @@ set -e -x Error() { echo "ERROR: $(tput bold;tput setaf 7;tput setab 1)$*$(tput sgr0)" >&2; } -# Download architecture-independent packages -Getpkg() { local P="$1"; local R="${2-sid}"; local WEB="https://packages.debian.org/${R}/all/${P}/download"; - local URL="$(wget -qO- "$WEB"|grep -o '[^"]\+ftp.fr.debian.org/debian[^"]\+\.deb')"; - [ -z "$URL" ] && return 1; wget -qO "${P}.deb" "$URL" && dpkg -i "${P}.deb"; echo "Ret=$?"; } - [ "$(id -u)" == 0 ] || exit 1 # Identify distribution @@ -76,7 +75,7 @@ echo 'APT::Periodic::Download-Upgradeable-Packages "1";' > /etc/apt/apt.conf.d/2 apt-get update apt-get dist-upgrade -y --force-yes apt-get install -y lsb-release xz-utils ssh sudo ca-certificates most less lftp \ - time bash-completion htop bind9-host mc lynx ncurses-term + time bash-completion htop bind9-host mc lynx ncurses-term aptitude ln -svf /usr/bin/host /usr/local/bin/mx # Input @@ -198,19 +197,20 @@ adduser --gecos "" ${U} K="PUBLIC-KEY" S="/home/${U}/.ssh";mkdir --mode 700 "$S";echo "$K" >> "${S}/authorized_keys2";chown -R ${U}:${U} "$S" adduser ${U} sudo -# Expire pass +# Expire password # passwd -e ${U} # Change root and other passwords to "*" editor /etc/shadow +read -s -p "SSH port? " SSH_PORT # sshd on another port -sed 's/^Port 22$/#Port 22\nPort 3022/' -i /etc/ssh/sshd_config +sed 's/^Port 22$/#Port 22\nPort ${SSH_PORT}/' -i /etc/ssh/sshd_config # Disable root login sed 's/^PermitRootLogin yes$/PermitRootLogin no/' -i /etc/ssh/sshd_config # Disable password login for sudoers echo -e 'Match Group sudo\n PasswordAuthentication no' >> /etc/ssh/sshd_config # Add IP blocking -# See: $D/security/README.md +# See: ${D}/security/README.md editor /etc/hosts.deny service ssh restart netstat -antup|grep sshd @@ -222,6 +222,11 @@ logout sudo su - || exit D="/root/src/debian-server-tools-master" +# Download architecture-independent packages +Getpkg() { local P="$1"; local R="${2-sid}"; local WEB="https://packages.debian.org/${R}/all/${P}/download"; + local URL="$(wget -qO- "$WEB"|grep -o '[^"]\+ftp.fr.debian.org/debian[^"]\+\.deb')"; + [ -z "$URL" ] && return 1; wget -qO "${P}.deb" "$URL" && dpkg -i "${P}.deb"; echo "Ret=$?"; } + # Hardware lspci [ -f /proc/modules ] && lsmod || echo "WARNING: monolithic kernel" @@ -230,22 +235,23 @@ lspci clear; cat /proc/mdstat; cat /proc/partitions pvdisplay && vgdisplay && lvdisplay ls -1 /etc/default/* -head -n1000 /etc/default/* | grep -v "^#\|^$" | grep --color -A1000 "^==> " +head -n 1000 /etc/default/* | grep -v "^#\|^$" | grep --color -A1000 "^==> " # /tmp in RAM TOTAL_MEM="$(grep MemTotal /proc/meminfo|sed 's;.*[[:space:]]\([0-9]\+\)[[:space:]]kB.*;\1;')" -[ "$TOTAL_MEM" -gt $((2047 * 1024)) ] && sed -i 's/^#RAMTMP=no$/RAMTMP=yes/' /etc/default/tmpfs +[ "$TOTAL_MEM" -gt $((2049 * 1024)) ] && sed -i 's/^#RAMTMP=no$/RAMTMP=yes/' /etc/default/tmpfs # Mount points # -editor /etc/fstab +clear; editor /etc/fstab clear; cat /proc/mounts swapoff -a; swapon -a; cat /proc/swaps # Create a swap file -# dd if=/dev/zero of=/swap0 bs=1M count=768 -# chmod 0600 /swap0 -# echo "/swap0 none swap sw 0 0" >> /etc/fstab +dd if=/dev/zero of=/swap0 bs=1M count=768 +chmod 0600 /swap0 +mkswap /swap0 +echo "/swap0 none swap sw 0 0" >> /etc/fstab grep "\S\+\s\+/\s.*relatime" /proc/mounts || echo "ERROR: no relAtime for rootfs" @@ -254,11 +260,11 @@ uname -a # List kernels apt-cache policy "linux-image-3.*" #apt-get install linux-image-amd64=KERNEL-VERSION -ls -l /lib/modules/ +clear; ls -l /lib/modules/ +ls -latr /boot/ # Verbose boot sed -i 's/^#*VERBOSE=no$/VERBOSE=yes/' /etc/default/rcS dpkg -l | grep "grub" -ls -latr /boot/ # OVH Kernel "made-in-ovh" # https://gist.github.com/szepeviktor/cf6b60ac1b2515cb41c1 # Linode Kernels: auto renew on reboot @@ -276,9 +282,11 @@ editor /etc/motd # Networking editor /etc/network/interfaces +# auto eth0 # iface eth0 inet static # address IP # netmask 255.255.255.0 +# #netmask 255.255.254.0 # gateway GATEWAY ifconfig -a route -n -4 @@ -297,28 +305,30 @@ editor /etc/resolv.conf # # DC1-IT 62.149.128.4 62.149.132.4 # DC3-CZ 81.2.192.131 81.2.193.227 +# +# Vultr resolvers +# +# Frankfurt 108.61.10.10 ping6 -c 4 ipv6.google.com host -v -tA example.com|grep "^example\.com\.\s*[0-9]\+\s*IN\s*A\s*93\.184\.216\.34$"||echo "DNS error" # View network Graph v4/v6 # http://bgp.he.net/ip/${IP} -# Set up MYATTACKERS chain -iptables -N MYATTACKERS -iptables -I INPUT -j MYATTACKERS -iptables -A MYATTACKERS -j RETURN -# For management scripts see: ${D}/security/myattackers.sh +# MYATTACKERS chain +# See: ${D}/security/myattackers.sh # Hostname # Set A record and PTR record # Consider: http://www.iata.org/publications/Pages/code-search.aspx # http://www.world-airport-codes.com/ -H="HOST-NAME" +read -r -p "Host name? " H # Search for the old hostname grep -ir "$(hostname)" /etc/ hostname "$H" echo "$H" > /etc/hostname echo "$H" > /etc/mailname +editor /etc/hosts # 127.0.0.1 localhost # 127.0.1.1 localhost # ::1 ip6-localhost ip6-loopback @@ -329,10 +339,9 @@ echo "$H" > /etc/mailname # # # ORIGINAL-PTR $(host "$IP") # IP.IP.IP.IP HOST.DOMAIN HOST -editor /etc/hosts # Locale and timezone -locale; locale -a +clear; locale; locale -a dpkg-reconfigure locales cat /etc/timezone dpkg-reconfigure tzdata @@ -352,7 +361,7 @@ update-passwd -v --dry-run # Sanitize packages (-hardware-related +monitoring -daemons) # 1. Delete not-installed packages -dpkg -l|grep -v "^ii" +clear; dpkg -l|grep -v "^ii" # 2. Usually unnecessary packages apt-get purge \ at ftp dc dbus rpcbind exim4-base exim4-config python2.6-minimal python2.6 \ @@ -367,8 +376,8 @@ dpkg -l|grep -E "xe-guest-utilities|dkms" # See: ${D}/package/vmware-tools-wheezy.sh vmware-toolbox-cmd stat sessionid # 4. Hardware related -dpkg -l|grep -E -w "dmidecode|eject|laptop-detect|usbutils|kbd|console-setup-linux\ -|acpid|fancontrol|hddtemp|lm-sensors|sensord|smartmontools|mdadm" +dpkg -l|grep -E -w "dmidecode|eject|laptop-detect|usbutils|kbd|console-setup\ +|acpid|fancontrol|hddtemp|lm-sensors|sensord|smartmontools|mdadm|popularity-contest" # 5. Non-stable packages dpkg -l|grep "~[a-z]\+" dpkg -l|grep -E "~squeeze|~wheezy|python2\.6" @@ -388,30 +397,29 @@ dpkg -l | most apt-get autoremove --purge # Essential packages -apt-get install -y localepurge unattended-upgrades \ - apt-listchanges cruft debsums heirloom-mailx iptables-persistent bootlogd \ - ntpdate apg dos2unix strace ccze mtr-tiny gcc make colordiff +apt-get install -y localepurge unattended-upgrades apt-listchanges cruft debsums \ + whois unzip heirloom-mailx iptables-persistent bootlogd goaccess\ + ntpdate apg dos2unix strace ccze mtr-tiny git colordiff gcc libc6-dev make # Backports # @wheezy apt-get install -t wheezy-backports -y rsyslog whois git goaccess init-system-helpers -apt-get install -y goaccess git # debsums cron weekly sed -i 's/^CRON_CHECK=never/CRON_CHECK=weekly/' /etc/default/debsums # Check user cron jobs -${D}/tools/catconf /var/spool/cron/crontabs/* +clear; ${D}/tools/catconf /var/spool/cron/crontabs/* # Automatic package updates echo "unattended-upgrades unattended-upgrades/enable_auto_updates boolean true"|debconf-set-selections -v dpkg-reconfigure -f noninteractive unattended-upgrades # Sanitize files -HOSTING_COMPANY="HOSTING-COMPANY" +rm -vrf /var/lib/clamav /var/log/clamav +read -r -p "Hosting company? " HOSTING_COMPANY find / -iname "*${HOSTING_COMPANY}*" grep -ir "${HOSTING_COMPANY}" /etc/ dpkg -l | grep -i "${HOSTING_COMPANY}" cruft --ignore /dev | tee cruft.log -rm -vrf /var/lib/clamav /var/log/clamav # Find broken symlinks find / -type l -xtype l -not -path "/proc/*" debsums --all --changed | tee debsums-changed.log @@ -419,6 +427,9 @@ debsums --all --changed | tee debsums-changed.log # Custom APT repositories editor /etc/apt/sources.list.d/others.list && apt-get update +cd /root/ +mkdir dist-mod && cd dist-mod/ + # Get pip wget https://bootstrap.pypa.io/get-pip.py python3 get-pip.py @@ -426,7 +437,7 @@ python2 get-pip.py # Detect whether your container is running under a hypervisor wget -O slabbed-or-not.zip https://github.com/kaniini/slabbed-or-not/archive/master.zip -unzip slabbed-or-not.zip && rm -f slabbed-or-not.zip +unzip slabbed-or-not.zip && rm -vf slabbed-or-not.zip cd slabbed-or-not-master/ && make && ./slabbed-or-not|tee ../slabbed-or-not.log && cd .. # rsyslogd immark plugin @@ -442,10 +453,6 @@ D="$(pwd)/debian-server-tools" rm -vrf /root/src/debian-server-tools-master/ cd ${D}; ls tools/ | xargs -I "%%" ./install.sh tools/%% -# Make cron log all failed jobs (exit status != 0) -sed -i "s/^#\s*\(EXTRA_OPTS='-L 5'\)/\1/" /etc/default/cron || echo "ERROR: cron-default" -service cron restart - # CPU grep -E "model name|cpu MHz|bogomips" /proc/cpuinfo cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor @@ -456,8 +463,13 @@ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor declare -i CPU_COUNT="$(grep -c "^processor" /proc/cpuinfo)" [ "$CPU_COUNT" -gt 1 ] && apt-get install -y irqbalance && cat /proc/interrupts +# Make cron log all failed jobs (exit status != 0) +sed -i "s/^#\s*\(EXTRA_OPTS='-L 5'\)/\1/" /etc/default/cron || echo "ERROR: cron-default" +service cron restart + # Time synchronization cd ${D}; ./install.sh monitoring/ntpdated +editor /etc/default/ntpdate # Set nearest time server: http://www.pool.ntp.org/en/ # NTPSERVERS="0.uk.pool.ntp.org 1.uk.pool.ntp.org 2.uk.pool.ntp.org 3.uk.pool.ntp.org" # NTPSERVERS="0.de.pool.ntp.org 1.de.pool.ntp.org 2.de.pool.ntp.org 3.de.pool.ntp.org" @@ -466,7 +478,6 @@ cd ${D}; ./install.sh monitoring/ntpdated # NTPSERVERS="0.hu.pool.ntp.org 1.hu.pool.ntp.org 2.hu.pool.ntp.org 3.hu.pool.ntp.org" # OVH # NTPSERVERS="ntp.ovh.net" -editor /etc/default/ntpdate # µnscd apt-get install -y unscd @@ -498,27 +509,27 @@ echo "This is a test mail."|mailx -s "[first] Subject of the first email" ADDRES # Send-only servers don't have local domain names. # They should have an MX record pointing to the smarthost. # Smarthost should receive all emails with send-only server's domain name. -apt-get install -y courier-mta courier-mta-ssl +clear; apt-get install -y courier-mta courier-mta-ssl # Fix dependency on courier-authdaemon sed -i '1,20s/^\(#\s\+Required-Start:\s.*\)$/\1 courier-authdaemon/' /etc/init.d/courier-mta update-rc.d courier-mta defaults # Check for other MTA-s dpkg -l | grep -E "postfix|exim" cd ${D}; ./install.sh mail/courier-restart.sh -# Host name +# Smarthost editor /etc/courier/esmtproutes # : %SMART-HOST%,587 /SECURITY=REQUIRED # : smtp.mandrillapp.com,587 /SECURITY=REQUIRED # From jessie on - requires ESMTP_TLS_VERIFY_DOMAIN=1 and TLS_VERIFYPEER=PEER # : %SMART-HOST%,465 /SECURITY=SMTPS -editor /etc/courier/esmtproutes +editor /etc/courier/esmtpauthclient # smtp.mandrillapp.com,587 MANDRILL@ACCOUNT API-KEY openssl dhparam -out /etc/courier/dhparams.pem 2048 editor /etc/courier/esmtpd # ADDRESS=127.0.0.1 +# TLS_DHPARAMS=/etc/courier/dhparams.pem # ESMTPAUTH="" # ESMTPAUTH_TLS="" -# TLS_DHPARAMS=/etc/courier/dhparams.pem editor /etc/courier/esmtpd-ssl # SSLADDRESS=127.0.0.1 # TLS_DHPARAMS=/etc/courier/dhparams.pem @@ -527,43 +538,36 @@ editor /etc/courier/smtpaccess/default # :0000:0000:0000:0000:0000:0000:0000:0001 allow,RELAYCLIENT editor /etc/courier/me # Check MX record -host -tMX $(cat /etc/courier/me) +host -t MX $(cat /etc/courier/me) editor /etc/courier/defaultdomain editor /etc/courier/dsnfrom editor /etc/courier/locals # localhost +# # Remove own hostname! editor /etc/courier/aliases/system courier-restart.sh # Allow unauthenticated SMTP traffic from this server on the smarthost +# # editor /etc/courier/smtpaccess/default # %%IP%%allow,RELAYCLIENT,AUTH_REQUIRED=0 +# # Receive bounce messages on the smarthost +# # editor /etc/courier/aliases/system # @HOSTNAME.TLD: LOCAL-USER # editor /var/mail/DOMAIN/USER/.courier-default # LOCAL-USER -echo "This is a test mail."|mailx -s "[first] Subject of the first email" ADDRESS - -# Fail2ban -# https://packages.qa.debian.org/f/fail2ban.html -Getpkg geoip-database-contrib -apt-get install -y geoip-bin recode python3-pyinotify -# apt-get install -y fail2ban -Getpkg fail2ban -mc ${D}/security/fail2ban-conf/ /etc/fail2ban/ -# Config: fail2ban.local -# Jails: jail.local -# /filter.d: apache-combined.local, apache-asap.local -# /action.d: sendmail-geoip-lines.local -service fail2ban restart +# courier-restart.sh +echo "This is a t3st mail."|mailx -s "[first] Subject of the 1st email" viktor@szepe.net # Apache 2.4 # @wheezy apt-get install -y -t wheezy-experimental apache2-mpm-itk apache2-utils libapache2-mod-fastcgi apt-get install -y apache2-mpm-itk apache2-utils a2enmod actions rewrite headers deflate expires proxy_fcgi +a2enmod ssl mkdir /etc/apache2/ssl && chmod 750 /etc/apache2/ssl cp -v ${D}/webserver/apache-conf-available/* /etc/apache2/conf-available/ -cp -vf ${D}/webserver/apache-sites-available/* /etc/apache2/sites-available/ +yes|cp -vf ${D}/webserver/apache-sites-available/* /etc/apache2/sites-available/ echo -e "User-agent: *\nDisallow: /\n" > /var/www/html/robots.txt # Use php-fpm.conf settings per site @@ -572,20 +576,14 @@ editor /etc/apache2/conf-enabled/security.conf # ServerTokens Prod editor /etc/apache2/apache2.conf # LogLevel info -# @TODO fcgi://port,path?? ProxyPassMatch ^/.*\.php$ unix:/var/run/php5-fpm.sock|fcgi://127.0.0.1:9000/var/www/website/html +# @TODO fcgi://port,path?? ProxyPassMatch "^/.*\.php$" "unix:/var/run/php5-fpm.sock|fcgi://127.0.0.1:9000/var/www/website/html" -# mod_pagespeed for poorly written themes and plugins +# mod_pagespeed for poorly written websites apt-get install -y mod-pagespeed-stable # Remove duplicate ls -l /etc/apt/sources.list.d/*pagespeed* #rm -v /etc/apt/sources.list.d/mod-pagespeed.list -# Add the development website -# See: ${D}/webserver/add-prg-site.sh - -# Add a website -# See: ${D}/webserver/add-site.sh - # Nginx 1.8 apt-get install -y nginx-lite # Nginx packages: lite, full, extra @@ -607,6 +605,19 @@ ngx-conf --disable default cp -vf sites-available/no-default ${NGXC}/sites-available ngx-conf --enable no-default +# Fail2ban +# https://packages.qa.debian.org/f/fail2ban.html +Getpkg geoip-database-contrib +apt-get install -y geoip-bin recode python3-pyinotify +# apt-get install -y fail2ban +Getpkg fail2ban +mc ${D}/security/fail2ban-conf/ /etc/fail2ban/ +# Config: fail2ban.local +# Jails: jail.local +# /filter.d: apache-combined.local, apache-instant.local, courier-smtp.local, recidive.local +# /action.d: cloudflare.local +service fail2ban restart + # PHP 5.6 apt-get install -y php5-apcu php5-cli php5-curl php5-fpm php5-gd \ php5-mcrypt php5-mysqlnd php5-readline php5-sqlite php-pear php5-dev @@ -629,7 +640,7 @@ cp -v ${D}/webserver/php5fpm-pools/* /etc/php5/fpm/ mkdir -p /usr/local/lib/php5 cp -v ${D}/webserver/sessionclean5.5 /usr/local/lib/php5/ # PHP 5.6+ -echo "15 * * * * root [ -x /usr/local/lib/php5/sessionclean5.5 ] && /usr/local/lib/php5/sessionclean5.5" \ +echo -e "15 *\t* * *\troot\t[ -x /usr/local/lib/php5/sessionclean5.5 ] && /usr/local/lib/php5/sessionclean5.5" \ > /etc/cron.d/php5-user # @FIXME PHP timeouts @@ -656,12 +667,23 @@ php5enmod -s fpm suhosin # suhosin.post.max_array_index_length = 128 # suhosin.request.max_array_index_length = 128 +# No FPM pools -> no restart + +cd ${D}; ./install.sh webserver/webrestart.sh + +# Add the development website +# See: ${D}/webserver/add-prg-site.sh + +# Add a website +# See: ${D}/webserver/add-site.sh + # MariaDB apt-get install -y mariadb-server-10.0 mariadb-client-10.0 read -e -p "MYSQL_PASSWORD? " MYSQL_PASSWORD echo -e "[mysql]\nuser=root\npass=${MYSQL_PASSWORD}\ndefault-character-set=utf8" >> /root/.my.cnf +echo -e "[mysqldump]\nuser=root\npass=${MYSQL_PASSWORD}\ndefault-character-set=utf8" >> /root/.my.cnf chmod 600 /root/.my.cnf -editor /root/.my.cnf +#editor /root/.my.cnf # wp-cli WPCLI_URL="https://raw.github.com/wp-cli/builds/gh-pages/phar/wp-cli.phar" @@ -727,6 +749,30 @@ lynx 127.0.0.1:2812 # Munin - network-wide graphing # See: ${D}/monitoring/munin/munin-debian-setup.sh +# Aruba ExtraControl (serclient) +# http://admin.dc3.arubacloud.hu/Manage/Serial/SerialManagement.aspx +wget -nv http://admin.dc3.arubacloud.hu/Installers/debian/aruba-serclient_0.01-1_all.deb +dpkg -i aruba-serclient_*_all.deb +# Set log level +echo -e "[LOG]\nlevel = 20" >> /opt/serclient/serclient.ini +# Comment out "if getRestartGUID(remove=False) == None: rf.doRollover()" +editor +159 /opt/serclient/tools.py +# Add logrotate +editor /etc/logrotate.d/serclient +# /var/log/serclient.log { +# weekly +# rotate 15 +# compress +# delaycompress +# notifempty +# create 640 root root +# postrotate +# if /etc/init.d/serclient status > /dev/null ; then \ +# /etc/init.d/serclient restart > /dev/null; \ +# fi; +# endscript +# } + # node.js apt-get install -y iojs # Install packaged under /usr/local/ @@ -736,9 +782,15 @@ npm install -g less-plugin-clean-css # Logrotate periods # -# syslog - /week*15 -# apache - /day*90 -# mail - /week*15 +editor /etc/logrotate.d/rsyslog +# weekly +# rotate 15 +# # /var/log/mail.log +# weekly +# rotate 15 +editor /etc/logrotate.d/apache2 +# daily +# rotate 90 # Clean up apt-get autoremove --purge @@ -750,5 +802,5 @@ echo 'Acquire::Queue-mode "access"; Acquire::http::Dl-Limit "1000";' > /etc/apt/ tar cJf "/root/${H//./-}_etc-backup_$(date --rfc-3339=date).tar.xz" /etc/ # Clients and services -editor /root/clients.list -editor /root/services.list +cp -v ${D}/server.yml /root/ +editor /root/server.yml diff --git a/mail/README.md b/mail/README.md index f7852b9e..257b16ce 100644 --- a/mail/README.md +++ b/mail/README.md @@ -171,19 +171,18 @@ http://www.returnpath.com/solution-content/dmarc-support/what-is-dmarc/ - Who (name, email address, why) is subscribed - Unsubscribe link -##### Headers +##### Email headers -- List-Unsubscribe: -- Precedence: bulk -- Return-Path: -- Reply-to: -- From: -- To: -- Subject: +- List-Unsubscribe: URL (invisible) +- Precedence: bulk (invisible) +- Return-Path: bounce@addre.ss (invisible) +- Reply-to: reply@addre.ss (invisible) +- From: sender@domain.net +- To: recipients@addre.ss ##### Others -- SMTP `MAIL FORM: ` +- SMTP `MAIL FORM: ` - HTML and plain payload - From address SPF `include:servers.mcsv.net` - [Bulk Senders Guidelines by Google](https://support.google.com/mail/answer/81126) diff --git a/monitoring/Speedtest.md b/monitoring/Speedtest.md index e7b71566..c6464f6f 100644 --- a/monitoring/Speedtest.md +++ b/monitoring/Speedtest.md @@ -1,9 +1,16 @@ -Global networking tools +# Global networking tools -### DNS lookup +### DNS propagation checker - https://www.whatsmydns.net/ +- https://dnschecker.org/ +- http://viewdns.info/propagation/ +- https://www.nexcess.net/resources/tools/global-dns-checker/ + +### DNS lookup + - http://mxtoolbox.com/DNSLookup.aspx +- http://bgp.he.net/ ### Target country speedtest @@ -33,13 +40,13 @@ Global networking tools 1. syd-au-ping.vultr.com 1. wa-us-ping.vultr.com -- Cloud Monitor 50+ https://cloudmonitor.ca.com/en/ping.php PT +- Cloud Monitor 50+ https://asm.ca.com/en/ping.php PT - gtt 40+ http://www.as3257.net/lg/ PTB - SdV 4 http://bgpmap.sdv.fr/index.php PTB - HE http://lg.he.net/ PTB - TATA (de) http://lg.as6453.net/bin/lg.cgi PTB -- 10 http://www.locaping.com/ PT -- pingdom 1×Sweden http://tools.pingdom.com/ping/ PT +- LOCAPING 10 http://www.locaping.com/ PT +- pingdom 1×Sweden http://tools.pingdom.com/ping/ PT - http://www.super-ping.com/ PT - http://startping.com/ P - RIPE https://stat.ripe.net/widget/bgplay B https://stat.ripe.net/widget/list diff --git a/security/README.md b/security/README.md index 91402d07..e9dcc974 100644 --- a/security/README.md +++ b/security/README.md @@ -98,8 +98,8 @@ sshd: 223.0.0.0/8 ### CloudFlare API IP banning -mode: block / challenge / whitelist -target: country / ip +mode: block | challenge | whitelist +target: country | ip Value would be an IP, /16 /24 or a 2-letter country code. The notes field can be left empty or removed if you don't want to add any. @@ -111,10 +111,10 @@ Replace YOUR-ZONE-ID with the zone identifier for the zone retrieved via an API GET to `https://api.cloudflare.com/client/v4/zones/` with your API details. ``` -curl 'https://api.cloudflare.com/client/v4/user/firewall/packages/access_rules/rules' \ - --data-binary '{"mode":"block","notes":"","configuration":{"value":"1.2.3.4","target":"ip"}}' \ +curl --data-binary '{"mode":"block","notes":"","configuration":{"value":"1.2.3.4","target":"ip"}}' \ --compressed -H 'content-type: application/json' \ - --header "X-Auth-Key: YOUR-API-KEY" --header "X-Auth-Email: YOUR-EMAIL-ADDRESS" --verbose + --header "X-Auth-Key: API-KEY" --header "X-Auth-Email: EMAIL-ADDRESS" --verbose \ + 'https://api.cloudflare.com/client/v4/user/firewall/packages/access_rules/rules' ``` ### Incapsula IP ranges @@ -123,7 +123,9 @@ https://incapsula.zendesk.com/hc/en-us/articles/200627570-Restricting-direct-acc resp_format: json | apache | nginx | iptables | text -`curl -k -s --data "resp_format=apache" https://my.incapsula.com/api/integration/v1/ips` +``` +curl -k -s --data 'resp_format=apache' 'https://my.incapsula.com/api/integration/v1/ips' +``` ### Difference between “BEGIN RSA PRIVATE KEY” and “BEGIN PRIVATE KEY” diff --git a/security/fail2ban-conf/filter.d/apache-instant.local b/security/fail2ban-conf/filter.d/apache-instant.local index c7a0e543..dd755501 100644 --- a/security/fail2ban-conf/filter.d/apache-instant.local +++ b/security/fail2ban-conf/filter.d/apache-instant.local @@ -10,7 +10,8 @@ before = apache-common.conf # apache-overflows # apache-shellshock # wordpress-fail2ban/instant -# apache-botsearch-custom +# no directory index +# apache-botsearch-custom # TODO 404 /wp* @@ -41,6 +42,8 @@ failregex = ^%(_apache_error_client)s ((AH0013[456]: )?Invalid (method|URI) in r ^%(_apache_error_client)s (AH01215: )?/bin/(ba)?sh: warning: HTTP_.*?: ignoring function definition attempt(, referer: \S+)?\s*$ ^%(_apache_error_client)s (AH01215: )?/bin/(ba)?sh: error importing function definition for `HTTP_.*?'(, referer: \S+)?\s*$ ^%(_apache_error_client)s (FastCGI: server "/\S*" stderr: |AH01071: Got error ')(PHP message: )?Break-in attempt detected: .*(, referer: \S+)?\s*$ + ^%(_apache_error_client)s AH01276: Cannot serve directory /.+/: No matching DirectoryIndex \(\S+\) found, and server-generated directory index forbidden by Options directive\s*$ + ignoreregex = diff --git a/security/fail2ban-conf/filter.d/courier-smtp-instant.local b/security/fail2ban-conf/filter.d/courier-smtp-instant.local new file mode 100644 index 00000000..cf16ffd8 --- /dev/null +++ b/security/fail2ban-conf/filter.d/courier-smtp-instant.local @@ -0,0 +1,18 @@ +# Fail2Ban filter to block relay attempts though a Courier smtp server +# +# + +[INCLUDES] + +# Read common prefixes. If any customizations available -- read them from +# common.local +before = common.conf + +[Definition] + +_daemon = courieresmtpd + +# Password tries: 123, 1234, 12345, 123456, 1234567 +failregex = ^%(__prefix_line)serror,relay=,msg="535 Authentication failed\.",cmd: (MTIz|MTIzNA==|MTIzNDU=|MTIzNDU2|MTIzNDU2Nw==)$ + +ignoreregex = diff --git a/security/myattackers.sh b/security/myattackers.sh index a597cb21..dd572e2e 100755 --- a/security/myattackers.sh +++ b/security/myattackers.sh @@ -242,11 +242,11 @@ while getopts ":ip:t:l:uzh" OPT; do Usage ;; \?) - Error_msg "Invalid option: -$OPTARG" + Error_msg "Invalid option: -${OPTARG}" Usage ;; :) - Error_msg "Option -$OPTARG requires an argument." + Error_msg "Option -${OPTARG} requires an argument." Usage ;; esac @@ -268,7 +268,7 @@ case "$PROTOCOL" in PROTOCOL_OPTION="" ;; *) - Error_msg "Invalid protocol: ($PROTOCOL)" + Error_msg "Invalid protocol: (${PROTOCOL})" Usage ;; esac diff --git a/server.yml b/server.yml index 9bd63af8..68ed1062 100644 --- a/server.yml +++ b/server.yml @@ -1,3 +1,8 @@ +# Server installation +install: + date: 2015-MM-DD + operating-system: Debian jessie 8.1 + # Clients using this server clients: @@ -83,7 +88,7 @@ services: type: vhost description: vhost.name can-send-email: - type:vhost + type: vhost description: PHP script # Consumed remote services @@ -100,7 +105,7 @@ dependencies: identify: $IP # Custom data directories -data: +data dirs: directory name: /path/to/dir configuration files: /etc diff --git a/webserver/README.md b/webserver/README.md index 677ccca7..1e8cf4fd 100644 --- a/webserver/README.md +++ b/webserver/README.md @@ -1,12 +1,21 @@ +### TCP port forwarder + +http://www.dest-unreach.org/socat/doc/socat.html#EXAMPLE_OPTION_REUSEADDR + +```bash +socat -d -d -lmlocal2 TCP4-LISTEN:80,bind=192.168.1.1,su=nobody,fork,reuseaddr TCP4:1.2.3.4:80,bind=192.168.10.2 +``` + ### File revving on nginx ```nginx location ~* ^(.+)\.\d\d+\.(js|css|png|jpg|jpeg|gif|ico)$ { + // TODO Add expiration etc. for js|css|png|jpg|jpeg|gif|ico files try_files $1.$2 /index.php?$args; } ``` -### Remove all comments and indentation (compact) from a PHP script +### Remove all comments and indentation from (compact) a PHP script ```bash php -w SCRIPT.php | sed 's/;/;\n/g' @@ -14,15 +23,27 @@ php -w SCRIPT.php | sed 's/;/;\n/g' ### Experimenting with webservers +#### nghttp2 + https://github.com/tatsuhiro-t/nghttp2/#nghttpx---proxy https://github.com/tatsuhiro-t/nghttp2/wiki/ServerBenchmarkRoundH210#results https://github.com/tatsuhiro-t/nghttp2/graphs/contributors +#### H2O + https://h2o.github.io/ -https://github.com/h2o/h2o/issues/200 (no FastCGI support yet) +https://github.com/h2o/h2o/issues/200 (FastCGI support) https://github.com/h2o/h2o/graphs/contributors +#### LiteSpeed + http://www.litespeedtech.com/products/litespeed-web-server/editions http://www.litespeedtech.com/products/litespeed-web-server/benchmarks/php-hello-world +#### Cherokee + https://github.com/cherokee/webserver#cherokee-web-server + +### Apache slow loris protection + +[RequestReadTimeout](https://httpd.apache.org/docs/2.4/mod/mod_reqtimeout.html) diff --git a/webserver/add-prg-site.sh b/webserver/add-prg-site.sh index 76240230..c33717cd 100644 --- a/webserver/add-prg-site.sh +++ b/webserver/add-prg-site.sh @@ -1,21 +1,24 @@ #!/bin/bash - +# # Apache add prg site. +# # Not a script but a manual. exit 0 U="web" -read -e -i "prg.$(hostname -d)" -p "prg domain: " DOMAIN +#read -e -i "prg.$(hostname -d)" -p "prg domain: " DOMAIN +read -e -i "prg.$(ip addr show dev eth0|sed -n 's/^\s*inet \([0-9\.]\+\)\b.*$/\1/p').xip.io" -p "prg domain: " DOMAIN adduser --disabled-password --gecos "" $U -echo "${U}@$(hostname -d): admin@$(hostname -d)" >> /etc/courier/aliases/system-user +echo "${U}@$(hostname -d): webmaster@$(hostname -d)" >> /etc/courier/aliases/system-user makealiases # Website directories cd /home/${U}/ mkdir website +chmod -v 750 website* cd website mkdir {session,tmp,html,pagespeed,backup,fastcgicache} @@ -50,10 +53,11 @@ echo " ${PRG_ROOT}/pif.php +wget -nv -O ${PRG_ROOT}/pif.php \ + https://github.com/szepeviktor/wordpress-plugin-construction/raw/master/shared-hosting-aid/php-vars.php # PHPMyAdmin +cd /home/${U}/website/html/ ${D}/package/phpmyadmin-get.sh cd phpMyAdmin-*-english cp -v config.sample.inc.php config.inc.php @@ -69,21 +73,26 @@ editor config.inc.php # $cfg['CaptchaLoginPrivateKey'] = ''; cd ../ -# PHP security check +# PHP Secure Configuration Checker git clone https://github.com/sektioneins/pcc.git -# Pool config -# env[PCC_ALLOW_IP] = 1.2.3.* # Set owner -chown -cR ${U}:${U} * +chown -cR ${U}:${U} cd /home/${U}/ # PHP pool cd /etc/php5/fpm/pool.d/ sed "s/@@USER@@/${U}/g" < ../Dev-pool.conf > ${U}.conf +# PHP Secure Configuration Checker allow IP address +# env[PCC_ALLOW_IP] = 1.2.3.* +editor ${U}.conf # Apache site cd /etc/apache2/sites-available sed -e "s/@@PRG_DOMAIN@@/${DOMAIN}/g" -e "s/@@SITE_USER@@/${U}/g" < Prg-site.conf > ${DOMAIN}.conf + +# Generate SSL certificate +mc /etc/apache2/ssl/ + a2ensite ${DOMAIN} ${D}/webserver/apache-resolve-hostnames.sh diff --git a/webserver/add-site.sh b/webserver/add-site.sh index 3f6bc29d..681248ec 100644 --- a/webserver/add-site.sh +++ b/webserver/add-site.sh @@ -1,6 +1,7 @@ #!/bin/bash - +# # Apache add new site. +# # Not a script but a manual. exit 0 @@ -10,11 +11,14 @@ exit 0 # See: ${D}/monitoring/domain-expiry.sh # See: ${D}/monitoring/dns-watch.sh -read -p "user name: " U -read -p "domain name: (without WWW) " DOMAIN +read -r -p "user name: " U +read -r -p "domain name: (without WWW) " DOMAIN adduser --disabled-password --gecos "" ${U} +# Add webserver to this group +adduser web ${U} + # Add system mail alias to direct bounces to one address # E.g. VIRTUAL-USERGROUP could be one client # USER@HOSTNAME: VIRTUAL-USERGROUP@HOSTNAME @@ -22,27 +26,23 @@ adduser --disabled-password --gecos "" ${U} # Set forwarding address on the smarthost # echo "RECIPIENT@DOMAIN.COM" > .courier-VIRTUAL-USERGROUP -editor /etc/courier/aliases/system-users +editor /etc/courier/aliases/system-user makealiases # * Add sudo permissions for real users to become this user cd /etc/sudoers.d/ # * Allow SSH key -mkdir /home/${U}/.ssh/ -cd /home/${U}/.ssh/ -editor authorized_keys2 -chmod -c 600 authorized_keys2 +S="/home/${U}/.ssh";mkdir --mode 700 "$S";touch "${S}/authorized_keys2";chown -R ${U}:${U} "$S" +editor "${S}/authorized_keys2" # Website directories -cd /home/${U}/ && mkdir -v website && cd website +cd /home/${U}/ +mkdir -v website +chmod -v 750 website* +cd website mkdir -v {session,tmp,html,pagespeed,backup,fastcgicache} -# * HTTP authentication -read -p "HTTP/auth user: " HTTP_USER -htpasswd -c ./htpasswords ${HTTP_USER} -chmod 600 ./htpasswords - # Install WordPress cd /home/${U}/website/html/ @@ -55,7 +55,6 @@ cd /home/${U}/website/html/ find -type f "(" -name ".htaccess" -o -name "*.php" -o -name "*.js" -o -name "*.css" ")" -exec dos2unix --keepdate "{}" ";" find -type f -exec chmod --changes 644 "{}" ";" find -type d -exec chmod --changes 755 "{}" ";" -chmod -v 750 website* find -name wp-config.php -exec chmod -v 400 "{}" ";" find -name settings.php -exec chmod -v 400 "{}" ";" find -name .htaccess -exec chmod -v 640 "{}" ";" diff --git a/webserver/apache-sites-available/Prg-site.conf b/webserver/apache-sites-available/Prg-site.conf index ae9b7bcd..eabfb267 100644 --- a/webserver/apache-sites-available/Prg-site.conf +++ b/webserver/apache-sites-available/Prg-site.conf @@ -20,6 +20,9 @@ AuthName "Please log in to ${AUTH_REALM}" AuthUserFile /home/${SITE_USER}/website/htpasswords + + Require all granted + ModPagespeed off diff --git a/webserver/apache-sites-available/Skeleton-site-ssl.conf b/webserver/apache-sites-available/Skeleton-site-ssl.conf index 681cd6b5..fb1eaf1a 100644 --- a/webserver/apache-sites-available/Skeleton-site-ssl.conf +++ b/webserver/apache-sites-available/Skeleton-site-ssl.conf @@ -69,7 +69,6 @@ # Filename revisioning RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.+)\.\d\d+\.(js|css|png|jpg|gif)$ $1.$2 [L] ## Missing JPEG-s @@ -77,8 +76,8 @@ #RewriteRule ^.*\.jpg$ /image.jpg [L] # Canonical redirect (insert WWW. here) - RewriteCond %{HTTP_HOST} !=${SITE_DOMAIN} - RewriteRule ^ %{REQUEST_SCHEME}://${SITE_DOMAIN}%{REQUEST_URI} [R=permanent,L] + RewriteCond %{HTTP_HOST} "!=${SITE_DOMAIN}" + RewriteRule "^" "%{REQUEST_SCHEME}://${SITE_DOMAIN}%{REQUEST_URI}" [R=permanent,L] # NO index files for robots diff --git a/webserver/apache-sites-available/Skeleton-site.conf b/webserver/apache-sites-available/Skeleton-site.conf index 8a521587..1ce1a80f 100644 --- a/webserver/apache-sites-available/Skeleton-site.conf +++ b/webserver/apache-sites-available/Skeleton-site.conf @@ -68,7 +68,6 @@ # Filename revisioning RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.+)\.\d\d+\.(js|css|png|jpg|gif)$ $1.$2 [L] ## Missing JPEG-s @@ -76,8 +75,8 @@ #RewriteRule ^.*\.jpg$ /image.jpg [L] # Canonical redirect (insert WWW. here) - RewriteCond %{HTTP_HOST} !=${SITE_DOMAIN} - RewriteRule ^ %{REQUEST_SCHEME}://${SITE_DOMAIN}%{REQUEST_URI} [R=permanent,L] + RewriteCond %{HTTP_HOST} "!=${SITE_DOMAIN}" + RewriteRule "^" "%{REQUEST_SCHEME}://${SITE_DOMAIN}%{REQUEST_URI}" [R=permanent,L] # Don't index files for robots @@ -89,7 +88,8 @@ ErrorDocument 500 "System failure. Sorry! Please try again. webmaster@szepe.net" # Log 404-s - LogLevel info ssl:notice pagespeed:notice + LogLevel info + #LogLevel info ssl:notice pagespeed:notice ErrorLog ${APACHE_LOG_DIR}/${SITE_USER}-error.log # CloudFlare, Incapsula #ErrorLog ${APACHE_LOG_DIR}/CF-${SITE_USER}-error.log diff --git a/webserver/apache-sites-available/_htaccess-snippets.conf b/webserver/apache-sites-available/_htaccess-snippets.conf index 0d057d84..619772d5 100644 --- a/webserver/apache-sites-available/_htaccess-snippets.conf +++ b/webserver/apache-sites-available/_htaccess-snippets.conf @@ -1,7 +1,18 @@ +# Maintenance static HTML placeholder file + + RewriteEngine On + RewriteCond %{REMOTE_ADDR} "!=1.2.3.4" + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + # WordPress canonical URL-s + RewriteRule "^.*/" "/index-maintenance.html" [L] + + # Redirect old pages RewriteEngine On RewriteRule "^old-url$" "http://site.net/new-url/" [R=permanent,L] + RewriteRule "^old-path/$" http://site.net/#hash/path [NE,R=permanent,L] # Block authentication attacks diff --git a/webserver/php5fpm-pools/Dev-pool.conf b/webserver/php5fpm-pools/Dev-pool.conf index ccaccfd1..f6ee13cb 100644 --- a/webserver/php5fpm-pools/Dev-pool.conf +++ b/webserver/php5fpm-pools/Dev-pool.conf @@ -7,6 +7,7 @@ listen = /run/php5-fpm-@@USER@@.sock listen.owner = @@USER@@ listen.group = www-data +#listen.group = web pm = ondemand pm.max_children = 20 diff --git a/webserver/php5fpm-pools/Skeleton-pool.conf b/webserver/php5fpm-pools/Skeleton-pool.conf index f7916558..0056603e 100644 --- a/webserver/php5fpm-pools/Skeleton-pool.conf +++ b/webserver/php5fpm-pools/Skeleton-pool.conf @@ -7,6 +7,7 @@ listen = /run/php5-fpm-@@USER@@.sock listen.owner = @@USER@@ listen.group = www-data +#listen.group = web pm = dynamic pm.max_children = 40 @@ -18,7 +19,8 @@ pm.max_spare_servers = 5 ;pm.status_path = /status -;php_admin_value[disable_functions] = exec,shell_exec,system,passthru,proc_open,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority +; @TODO What systems need these? +php_admin_value[disable_functions] = exec,shell_exec,system,passthru,proc_open,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority ;php_admin_flag[allow_url_fopen] = On php_admin_value[opcache.restrict_api] = /home/@@USER@@/website/ php_admin_value[opcache.validate_timestamps] = 0