Secure Apache2 and PHP on Ubuntu 16.04

Create /etc/apache2/sites-available/000-security.conf

$ sudo vi /etc/apache2/sites-available/000-security.conf
# Secure apache website

# Disable Trace HTTP Request
TraceEnable off

# Disable Signature
ServerSignature Off

# Disable Banner
ServerTokens Prod

# If enabled ssl (sudo a2enmod ssl)
# Use only TLS, Disable SSLv2, SSLv3
# SSLProtocol -ALL +TLSv1

# Disable Null and Weak Ciphers
# SSLCipherSuite ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM

# Disable Directory Listing
Options all -Indexes

# If enabled headers (sudo a2enmod headers)
# Disable x-powered by
Header always unset X-Powered-By
$ sudo a2ensite 000-security.conf

On ubuntu 16.04. The default php settings is good. Please make sure settings in php.ini

/etc/php/7.0/fpm/php.ini

/etc/php/7.0/apache2/php.ini

expose_php = Off
display_errors = Off

Reference: https://www.unixmen.com/ways-to-secure-your-ubuntu-14-04-server-running-lamp/

Apache2 configuration for proxy

Proxy Modules:

  • mod_proxy: The main proxy module for Apache that manages connections and redirects them.
  • mod_proxy_http: This module implements the proxy features for HTTP and HTTPS protocols.
  • mod_proxy_ftp: This module does the same but for FTP protocol.
  • mod_proxy_fcgi: FastCGI
  • mod_proxy_connect: This one is used for SSL tunnelling.
  • mod_proxy_ajp: Used for working with the AJP protocol.
  • mod_proxy_wstunnel: Used for working with web-sockets (i.e. WS and WSS).
  • mod_proxy_balancer: Used for clustering and load-balancing.
  • mod_proxy_hcheck: Dynamic health check of Balancer members (workers) for mod_proxy
  • mod_cache: Used for caching.
  • mod_headers: Used for managing HTTP headers.
  • mod_deflate: Used for compression.

Enable proxy:

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_html
sudo a2enmod xml2enc
sudo systemctl restart apache2

Example virtual host #1

<VirtualHost *:80>
    ServerName localhost
    ProxyPreserveHost On

    ProxyPass "/" "http://192.168.0.0:8080/"
    ProxyPassReverse "/" "http://192.168.0.1:8080/"

</VirtualHost>

Example virtual host #2

<VirtualHost *:80>
    ServerName localhost
    ProxyPreserveHost On

    ProxyPass "/subdir/" "http://192.168.0.221:8000/"
    ProxyPassReverse "/subdir/" "http://192.168.0.221:8000/"
     <Location "/subdir">
         ProxyPassReverse    /
         ProxyHTMLURLMap     / /subdir/
     </Location>

</VirtualHost>

Example virtual host #3 (Don’t proxy /static)

<VirtualHost *:80>
    ServerName localhost

    ProxyPreserveHost On
    ProxyPass "/" "http://192.168.0.221:8000/"
    ProxyPassReverse "/" "http://192.168.0.221:8000/"
    Alias /static/ /var/www/html/static/
    <Directory /var/www/html/static>
        Require all granted
    </Directory>
    <Location /static>
        ProxyPass "!"
    </Location>
</VirtualHost>

Enable load balancing:

sudo a2enmod proxy_balancer
sudo a2enmod proxy_hcheck
sudo systemctl restart apache2

Example load balancing #1

<Proxy balancer://myset>
    BalancerMember http://www2.example.com:8080
    BalancerMember http://www3.example.com:8080
    ProxySet lbmethod=bytraffic
</Proxy>

ProxyPass "/images/"  "balancer://myset/"
ProxyPassReverse "/images/"  "balancer://myset/"

Example load balancing #2 (www3 handles 3 times traffic and timeout is 1)

<Proxy balancer://myset>
    BalancerMember http://www2.example.com:8080
    BalancerMember http://www3.example.com:8080 loadfactor=3 timeout=1
    ProxySet lbmethod=bytraffic
</Proxy>

ProxyPass "/images"  "balancer://myset/"
ProxyPassReverse "/images"  "balancer://myset/"

Example failove

<Proxy balancer://myset>
    BalancerMember http://www2.example.com:8080
    BalancerMember http://www3.example.com:8080 loadfactor=3 timeout=1
    BalancerMember http://hstandby.example.com:8080 status=+H
    BalancerMember http://bkup1.example.com:8080 lbset=1
    BalancerMember http://bkup2.example.com:8080 lbset=1
    ProxySet lbmethod=byrequests
</Proxy>

ProxyPass "/images/"  "balancer://myset/"
ProxyPassReverse "/images/"  "balancer://myset/"

Balancer Manager (Don’t enable it in production)

<Location "/balancer-manager">
    SetHandler balancer-manager
    Require host localhost
</Location>

Controlling access proxy

<Proxy "*">
  Require ip 192.168.0
</Proxy>

Reference:

https://www.digitalocean.com/community/tutorials/how-to-use-apache-http-server-as-reverse-proxy-using-mod_proxy-extension
https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html
https://httpd.apache.org/docs/2.4/mod/mod_proxy.html

Install apache2, php, mysql client, drush on ubuntu 16.04

Install mysql-client

sudo apt install mysql-client

Install php7

sudo apt install php php-xml php-gd php-curl php-mcrypt php-mbstring php7.0-mbstring php-gettext php-mysql

Install apache2

sudo apt install apache2 libapache2-mod-php mod_dbd
sudo a2enmod rewrite

Install drush

$ php -r "readfile('https://s3.amazonaws.com/files.drush.org/drush.phar');" > drush
$ php drush core-status
$ chmod +x drush
$ sudo mv drush /usr/local/bin
$ drush init

Mailman on ubuntu 16.04

Install apache2

sudo apt install apache2

Install postfix

sudo apt install postfix

Install mailman

sudo apt install mailman

Setup apache

sudo cp /etc/mailman/apache.conf /etc/apache2/sites-available/mailman.conf
sudo a2ensite mailman.conf
sudo a2enmod cgi
sudo a2enmod cgid
sudo service apache2 restart

Activate the MTA option on the mailman config file (/etc/mailman/mm_cfg.py). Write or uncomment this line:

MTA = 'Postfix'

Run the script to generate aliases.

sudo /usr/lib/mailman/bin/genaliases

Use the postconf command to add the necessary configuration to /etc/postfix/main.cf:

sudo postconf -e 'relay_domains = lists.example.com'
sudo postconf -e 'transport_maps = hash:/etc/postfix/transport'
sudo postconf -e 'mailman_destination_recipient_limit = 1'
sudo postconf -e 'alias_maps = hash:/etc/aliases, hash:/var/lib/mailman/data/aliases'

In /etc/postfix/master.cf double check that you have the following transport:

mailman   unix  -       n       n       -       -       pipe
  flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
  ${nexthop} ${user}

Edit the file /etc/postfix/transport:

lists.example.com      mailman:

Now have Postfix build the transport map

sudo postmap -v /etc/postfix/transport

Then add mailman aliases in /etc/aliases

mailman:              "|/var/lib/mailman/mail/mailman post mailman"
mailman-admin:        "|/var/lib/mailman/mail/mailman admin mailman"
mailman-bounces:      "|/var/lib/mailman/mail/mailman bounces mailman"
mailman-confirm:      "|/var/lib/mailman/mail/mailman confirm mailman"
mailman-join:         "|/var/lib/mailman/mail/mailman join mailman"
mailman-leave:        "|/var/lib/mailman/mail/mailman leave mailman"
mailman-owner:        "|/var/lib/mailman/mail/mailman owner mailman"
mailman-request:      "|/var/lib/mailman/mail/mailman request mailman"
mailman-subscribe:    "|/var/lib/mailman/mail/mailman subscribe mailman"
mailman-unsubscribe:  "|/var/lib/mailman/mail/mailman unsubscribe mailman"

Fix permissions of aliases files and restart postfix

sudo chown root:list /var/lib/mailman/data/aliases
sudo chown root:list /etc/aliases
sudo newaliases
sudo /etc/init.d/postfix restart

Create mailman list

$ sudo newlist mailman mailmanadm@mydomain.com
  Enter the email of the person running the list: bhuvaneswaran at NOSPAM gmail.com
  Initial mailman password:
  To finish creating your mailing list, you must edit your /etc/aliases (orequivalent) file by adding the following lines, and possibly running the `newaliases' program:

  ## mailman mailing list
  mailman:              "|/var/lib/mailman/mail/mailman post mailman"
  mailman-admin:        "|/var/lib/mailman/mail/mailman admin mailman"
  mailman-bounces:      "|/var/lib/mailman/mail/mailman bounces mailman"
  mailman-confirm:      "|/var/lib/mailman/mail/mailman confirm mailman"
  mailman-join:         "|/var/lib/mailman/mail/mailman join mailman"
  mailman-leave:        "|/var/lib/mailman/mail/mailman leave mailman"
  mailman-owner:        "|/var/lib/mailman/mail/mailman owner mailman"
  mailman-request:      "|/var/lib/mailman/mail/mailman request mailman"
  mailman-subscribe:    "|/var/lib/mailman/mail/mailman subscribe mailman"
  mailman-unsubscribe:  "|/var/lib/mailman/mail/mailman unsubscribe mailman"

  Hit enter to notify mailman owner...

Edit /etc/aliases and run

$ sudo newaliases

Start mailman

$ sudo /etc/init.d/mailman start

Start mailman qrunner

$ sudo /var/lib/mailman/bin/mailmanctl start

Add members to list

$ vi ~/members
user1@mydomain.com
user2@mydomain.com

$ sudo /var/lib/mailman/bin/add_members -r ~/members -w y -a y mailman

Mailmain script location

/var/lib/mailman/bin

Change site password

sudo ./mmsitepass

Change list passoword

sudo ./change_pw -l <list name> -p <new password>

Discard pending post

sudo ./discard /var/lib/mailman/data/heldmsg-<list name>-<msg number>.pck

Reference:  https://help.ubuntu.com/community/Mailman

UFW command examples

sudo ufw status
sudo ufw status verbose
sudo ufw status numbered

sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw allow mysql

sudo ufw delete allow https

sudo ufw allow to any port 2345
sudo ufw delete allow to any port 2345

sudo ufw allow to any port 2345 proto udp
sudo ufw delete allow to any port 2345 proto udp

sudo ufw allow from 192.168.0.5 to any port 2345
sudo ufw delete allow from 192.168.0.5 to any port 2345

sudo ufw allow from 192.168.0.0/24 to any port 2345
sudo ufw delete allow from 192.168.0.0/24 to any port 2345

UFW, IPTABLES and IP FORWARDING

BY Default, UFW blocks IP Forwarding. To enable packet forwarding, two configuration files will need to be adjusted, in /etc/default/ufw change the DEFAULT_FORWARD_POLICY to “ACCEPT”:

DEFAULT_FORWARD_POLICY="ACCEPT"

Then edit /etc/ufw/sysctl.conf and uncomment:

net/ipv4/ip_forward=1
#for IPv6 forwarding uncomment:
net/ipv6/conf/default/forwarding=1

To enable IPv4 packet forwarding by editing /etc/sysctl.conf and uncomment the following line:

net.ipv4.ip_forward=1
# If you wish to enable IPv6 forwarding also uncomment:
net.ipv6.conf.default.forwarding=1

Execute the sysctl command to enable the new settings in the configuration file:

sudo sysctl -p

Create my-iptables-rules:

$ sudo vi /etc/network/if-up.d/my-iptables-rules
#!/bin/bash
FLAG="/tmp/my-iptables-settings"
if [ -f ${FLAG} ]; then
  echo "Already set my iptables rules. Skip it."
  exit 0
fi

#sample iptables rules
iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -o ppp0 -j MASQUERADE

touch ${FLAG}
exit 0

Reference:https://help.ubuntu.com/lts/serverguide/firewall.html

Configure Postfix as a mail gateway on Ubuntu

Edit /etc/postfix/main.cf

...
myorigin = /etc/mailname
mydestination =
local_recipient_maps =
local_transport = error:local mail delivery is disabled
virtual_alias_maps = hash:/etc/postfix/virtual
relay_domains = domain1.com domain2.com
parent_domain_matches_subdomains = debug_peer_list smtpd_access_maps
smtpd_relay_restrictions = permit_mynetworks reject_unauth_destination
smtpd_recipient_restrictions =
transport_maps = hash:/etc/postfix/transport
...

Edit /etc/postfix/master.cf to comment local engine

...
retry     unix  -       -       y       -       -       error
discard   unix  -       -       y       -       -       discard
# local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       y       -       -       lmtp
...

Create file /etc/postfix/virtual

postmaster     postmaster@domain1.com
abuse          abuse@domain1.com

Create file /etc/postfix/transport

domain1.com       smtp:10.0.224.10
domain2.com       smtp:10.0.218.11

Run postmap

sudo postmap /etc/postfix/virtual
sudo postmap /etc/postfix/transport

Restore Postfix

sudo systemctl restart postfix

Reference:http://www.postfix.org/STANDARD_CONFIGURATION_README.html

Postfix mail filtering on Ubuntu

Install postfix (config file is /etc/postfix/main.cf)

$ sudo apt install postfix
$ sudo dpkg-reconfigure postfix
$ sudo postconf -e 'home_mailbox = Maildir/'

Test mail

$ telnet mail.yourdomain.com 25
ehlo yourdomain.com
mail from: root@yourdomain.com
rcpt to: fmaster@yourdomain.com
data
Subject: My first mail for my domain

Hi,
Are you there?
regards,
Admin
. (and Enter In a new Line)
quit

Mail filtering

Check your fqdn name

$ hostname --fqdn

If it return localhost, change the first line in /etc/hosts.

$ sudo vi /etc/hosts
127.0.0.1  servername.domain.com localhost
$ sudo apt install amavisd-new spamassassin clamav-daemon
$ sudo apt install opendkim postfix-policyd-spf-python
$ sudo apt install pyzor razor
$ sudo apt install arj cabextract cpio nomarch pax rar unrar unzip zip jlha-utils lhasa
$ sudo adduser clamav amavis
$ sudo adduser amavis clamav
$ sudo vi /etc/default/spamassassin
...
ENABLED=1
...
$ sudo systemctl start spamassassin.service
use strict;

# You can modify this file to re-enable SPAM checking through spamassassin
# and to re-enable antivirus checking.

#
# Default antivirus checking mode
# Uncomment the two lines below to enable it
#

@bypass_virus_checks_maps = (
   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);


#
# Default SPAM checking mode
# Uncomment the two lines below to enable it
#

@bypass_spam_checks_maps = (
   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

1;  # insure a defined return
sudo vi /etc/amavis/conf.d/20-debian_defaults
...

$sa_spam_subject_tag = '***SPAM*** ';
# $sa_tag_level_deflt  = 2.0;  # add spam info headers if at, or above that level
# $sa_tag2_level_deflt = 6.31; # add 'spam detected' headers at that level
# $sa_kill_level_deflt = 6.31; # triggers spam evasive actions
# $sa_dsn_cutoff_level = 10;   # spam level beyond which a DSN is not sent
$sa_tag_level_deflt  = -999;  # add spam info headers if at, or above that level
$sa_tag2_level_deflt = 6.0; # add 'spam detected' headers at that level
$sa_kill_level_deflt = 21.0; # triggers spam evasive actions
$sa_dsn_cutoff_level = 4;   # spam level beyond which a DSN is not sent
...
# $final_spam_destiny       = D_BOUNCE;
$final_spam_destiny       = D_DISCARD;
...

$ sudo vi /etc/amavis/conf.d/50-user
...
@local_domains_acl = qw(.);
...

sudo systemctl restart amavis.service

sudo postconf -e 'content_filter = smtp-amavis:[127.0.0.1]:10024'

sudo vi  /etc/postfix/master.cf
# add to the end of the file
smtp-amavis     unix    -       -       -       -       2       smtp
        -o smtp_data_done_timeout=1200
        -o smtp_send_xforward_command=yes
        -o disable_dns_lookups=yes
        -o max_use=20

127.0.0.1:10025 inet    n       -       -       -       -       smtpd
        -o content_filter=
        -o local_recipient_maps=
        -o relay_recipient_maps=
        -o smtpd_restriction_classes=
        -o smtpd_delay_reject=no
        -o smtpd_client_restrictions=permit_mynetworks,reject
        -o smtpd_helo_restrictions=
        -o smtpd_sender_restrictions=
        -o smtpd_recipient_restrictions=permit_mynetworks,reject
        -o smtpd_data_restrictions=reject_unauth_pipelining
        -o smtpd_end_of_data_restrictions=
        -o mynetworks=127.0.0.0/8
        -o smtpd_error_sleep_time=0
        -o smtpd_soft_error_limit=1001
        -o smtpd_hard_error_limit=1000
        -o smtpd_client_connection_count_limit=0
        -o smtpd_client_connection_rate_limit=0
        -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters

...
#628       inet  n       -       y       -       -       qmqpd
pickup    unix  n       -       y       60      1       pickup
   -o content_filter=
   -o receive_override_options=no_header_body_checks
cleanup   unix  n       -       y       -       0       cleanup
...
 39 #628       inet  n       -       y       -       -       qmqpd
 40 pickup    unix  n       -       y       60      1       pickup
 41    -o content_filter=
 42    -o receive_override_options=no_header_body_checks
 43 cleanup   unix  n       -       y       -       0       cleanup
...

sudo systemctl restart postfix.service

Testing

$ telnet localhost 10024
Trying 127.0.0.1...
Connected to mail.cisdd.org.
Escape character is '^]'.
220 [127.0.0.1] ESMTP amavisd-new service ready

Checked /var/log/mail.log and found errors

Nov 21 14:26:36 mail-tiqc amavis[705]: (00705-01) (!)run_av (ClamAV-clamd) FAILED - unexpected , output="/var/lib/amavis/tmp/amavis-20161121T142636-00705-g5ZqbF_3/parts: lstat() failed: Permission denied. ERROR\n"
Nov 21 14:26:36 mail-tiqc amavis[705]: (00705-01) (!)ClamAV-clamd av-scanner FAILED: CODE(0x4bde0d0) unexpected , output="/var/lib/amavis/tmp/amavis-20161121T142636-00705-g5ZqbF_3/parts: lstat() failed: Permission denied. ERROR\n" at (eval 100) line 905.
Nov 21 14:26:36 mail-tiqc amavis[705]: (00705-01) (!)WARN: all primary virus scanners failed, considering backups

Fix error

$ sudo vi /etc/clamav/clamd.conf
...
AllowSupplementaryGroups true
...
$ sudo systemctl restart clamav-daemon