Showing posts with label IT. Show all posts
Showing posts with label IT. Show all posts

Thursday, 7 December 2023

Multi-Factor Authentication (MFA) over ssh

Free OTP MFA
Securing your internet-facing systems and data is of utmost importance. One critical aspect is ensuring secure access to your servers and protecting them from unauthorised access. Multi-Factor Authentication (MFA) adds an additional layer of security by requiring users to provide two or more pieces of evidence to authenticate themselves. In this tutorial, we will explore how to set up MFA for SSH using FreeOTP, an open-source OTP (One-Time Password) authenticator app.

Prerequisites

Before we begin, make sure you have the following:

  1. A Linux server (Ubuntu, CentOS, or any other distribution)
  2. Administrative access to the server
  3. A smartphone (iOS or Android) to install the FreeOTP app

Step 1: Installing FreeOTP

  1. On your smartphone, open the respective app store (Google Play Store or Apple App Store).
  2. Search for "FreeOTP" and install the app.
  3. Once installed, open the FreeOTP app.

Step 2: Configuring SSH for MFA

  1. Connect to your server using SSH with administrative privileges.
  2. Open the SSH configuration file using a text editor (e.g., nano or vi).
    •  sudo vi /etc/ssh/sshd_config

  3. Look for the ChallengeResponseAuthentication line and set it to "yes" if not already enabled.
  4. Add the following line to enable the use of Google Authenticator-compatible TOTP (Time-based One-Time Password) authentication:
    AuthenticationMethods publickey,password publickey,keyboard-interactive
  5.  Save and exit the SSH configuration file.

Step 3: Configuring the User for MFA

  1. In the SSH configuration file, find the Match User or AllowUsers section for the user you want to enable MFA for.
  2. Add the following line below the user entry:
    AuthenticationMethods publickey,password publickey,keyboard-interactive
  3. Save and exit the SSH configuration file.

Step 4: Restarting the SSH Service

  1. Restart the SSH service to apply the changes.
    • sudo systemctl restart sshd

Step 5: Enabling MFA for the User

  1. On your server, generate a secret key for the user using the following command:
    google-authenticator
  2. You will be presented with a series of prompts. Answer "y" for each of them to configure MFA.
  3. Scan the displayed QR code using the FreeOTP app on your smartphone.
  4. FreeOTP will add your server as a new account and start generating one-time passwords.
  5. Complete the setup process by following the on-screen instructions.

Step 6: Testing the MFA Setup

  1. Attempt to SSH into your server using the user account that has MFA enabled.
  2. After entering the username and password, you will be prompted for the verification code.
  3. Open the FreeOTP app on your smartphone and find the account associated with your server.
  4. Enter the current one-time password generated by FreeOTP.
  5. If the authentication is successful, you will gain access to your server.

By implementing MFA for SSH using FreeOTP, you have taken a significant step towards bolstering the security of your server. MFA provides an additional layer of protection against unauthorised access and greatly reduces the risk of compromised user credentials. Remember to enforce strong passwords and regularly update your system to maintain a robust security.

In future tutorials (when I get the time) I will show how to further harden your system with fail2ban and geoblocking.

Tuesday, 25 October 2022

The Ten Commandments of IT Operations

Ten Commandments of IT

These have been committed to memory for some time for me. I've finally decided to write them down. There's always been a bit fuzziness arounf the edges for these rules, so I suppose writing them here kinda sets them in stone. Anyway, for better or worse: 

1. What happens in the Server Room stays in the Server Room 

A long time ago when I was a poor Uni student, I had a temp job at "The Roofing Company". On my first day I was told tie a pallet of corrugated iron up using the strapping machine, which used a reel of metal strap. Nobody showed me how to use it and I fed the metal strap into the machine the wrong way round. The whole thing unspooled about 50 metres of strap onto the floor of the warehouse.

Later in the day a manager saw the mess and wanted to know who did it. A colleague looked directly at me and said "It was that bloke from Queensland who was here yesterday, wasn't it?" I nodded my head and the manager stormed away.

The lesson wasn't lost on me. Although I was to blame, the root cause lay in my not being provided training on the equipment.

Most of the time, your boss (or his boss) will be non-technical. Anyone who works in IT knows that the only people in IT who don't make mistakes are those who do no work. So don't throw your colleagues under the bus when they make mistakes. Do a root cause analysis. Discuss it amongst yourselves. Work out what changes need to be made to prevent it in the future. Then report - as a team - the actual root cause (or at least a plausible one). 

If the blame must lie with a person, then it lies with all of you, or the team leader.

2. Always have a second method of access - preferably more 

This applies to anything. If you have an electronic lock, have a physical key somewhere. If you use Citrix, make sure you have VPN as well. This includes having an extra admin account for all systems. Test the other methods of access.

By extension, have a backup internet link for inbound purposes, and out-of-bandwidth access for physical devices (such as ILO and DRAC), including the ability to power cycle them if necessary.

In short, eliminate all SPOF (Single Points Of Failure) for everything.

3. DDUF - Don't Do Updates on Friday 

Unless you like working over the weekend.

4. Take snapshots. Test Backups. 

Take snapshots of virtual machines before making changes. Also test your backups by doing a trial restore from time to time. On occasion, test a DR restore. 

5. ABC - Always Be Coding (or scripting) 

A lot of people who gain a tertiary qualification in IT will never write a line of code after they graduate. I don't care what it's in (BASH, Powershell, Python, C#, VBscript) make some form of coding a regular part of your work week. Don't let your skills atrophy. Sure, you CAN do your job without coding, but you can do it better WITH coding. 

6. A ten minute job takes ten minutes. Five minute jobs take two hours. 

We're all tempted to do something quick. Something that will only take five minutes. Usually we do them when we only have five minutes to spare. 

It's a trap. Those five minute jobs have been sitting there, gathering dust for some time, otherwise you would have done them some time ago. Chances are that your recollection of what really needs to be done has faded and there's more to the job than you remember. Or the conditions have changed. Or someone has done something else in the meantime. By contrast, ten minute jobs are usually on point. You do them regularly and know them well. They take ten minutes to do and that's it.

All of a sudden that five minute job is taking some time, and you can't roll back. You have to plough on through and finish in around two hours - usually after calling home to say you will be late. But that leads us to point 7.

7. Take breaks. Don't start anything new thirty minutes before you leave. 

Sometimes you need to come up for air. Take a break, go for a walk and come back with a fresh set of eyes. You will be way more productive this way than simply having your head down for several hours.

The second part of this is don't start any new work with thirty minutes (or less) to go. Step back, do some documentation, fill out a form, tidy your desk, plan tomorrow, reply to emails, rearrange files. There's always plenty of busy work to do other than starting something you realistically won't be able to finish, or feel pressured by time constraints. Any new work you do now won't be finished before you leave unless you work back late and chances are, you won't remember what you got up to tomorrow.

8. Sanity check everything. Even simple stuff. 

Whether it's code, configuration, deployment, modification etc. Get someone to check your work. You'd be surprised how easy it is for someone else to pick up some mistake you may have made. And if something you do does go south, you can always say you had someone check it out too.

9. Especially simply stuff. 

This particularly applies to 'simple things'. Mistakes are much easier to spot by others, but you can easily be blinded by proximity or familiarity. Forgot to remove a comment tag? Still logging in debug mode? Forget to enable that service?

Rookie mistakes, but we all do them. Not just rookies.

10. It's not yours. It never was.

Work with any system long enough, put enough of your blood, sweat and tears into something and it will feel like you own it. Like it's your baby.

It's not. It never was.

Sometimes, our recommendations will be ignored. We'll be told to do something we don't want to do. We'll be tempted to ignore that instruction because we know better.

Don't. It's not your system. You're just paid to maintain it. If your boss wants to melt it down and make ornaments of it, he can do that. It's his, not yours.


So that's it. Thirty years of wisdom condensed down into ten simple rules. If can add to the list, feel free to comment.


Tuesday, 23 August 2022

Ubuntu Server Runup Script

Ubuntu Server post-installation runup script
Ubuntu Server Post Installation Runup

Following on from my CentOS 7 runup script is a series of Ubuntu scripts I have written over time. They're presented as a "Work in Progress" which may or may not end. 

I started the Ubuntu scripts using the CentOS scripts as a base, however they diverged quickly to become both unique and specialised. With Ubuntu, the goal was to standardise server builds so they could be duplicated by others. So the scripts began to evolve into a partially menu based build system.

But as I said - it's a work in progress, and the comments reflect areas that need improvement. So, for better or worse, here's the best of about two dozen iterations.

Base Ubuntu 20.04 LTS Runup Script

The script follows after the commentary given here. The script was designed to be edited before use. It is divided loosely into several sections. While some parts have been improved to be interactive, the majority requires serious modification before you should even think of running it on a server.

1. Variables

The first section includes many variables. Most should be self-explanatory. Check these carefully and make any modifications you need. Only those variables used in sections you are using need to be used, the rest can be commented out. In particular, make sure the following is properly declared:

MAILFWD IP address of the email relay

EMAILINST Your email address
EMAILADMIN The server administrators email address
SNMPRO The SNMPv2 public community
SNMPRW The SNMPv2 private community
SNMPSRV IP address of the SNMP server

2. Updates & Cockpit

Next updates are applied and cockpit is installed. This will take a few minutes to run. Choose between cockpit and webmin - do not install both. Cockpit has a smaller footprint and is easier to use, but webmin is more versatile.

3. Active Directory Integration

If you are integrating with Active Directory, study this section carefully as it is a little buggy and doesn't trap a lot of exceptions. I'd welcome feedback here!

4. PCP Logging tools & Grafana

This section is very experimental. Use with care. Grafana is a powerful tool that is not utilised enough. However it does take significant time to configure.

5. Firewall & Fail2ban

UFW (Uncomplicated Firewall) is then setup to allow access to ssh and cockpit. Rate limiting is applied to ssh. Fail2ban is also installed.

6. Swap

Default swappiness for Ubuntu server is 60. This is way too high. This section changes it to 20. This is a simple change, but an important one.

7. Tools

Several system utilities are installed here. Comment or uncomment according to what you find useful. The utilities are:

  • wget - get files via http

  • telnet - telnet client
  • bind9utils - utlities for querying dns (such as dig)
  • nmap - network analysis tool
  • mlocate - Faster and more efficient file locator
  • mc - Midnight Commander (XTree like file system interface)
  • elinks - Text based broswer (has dependencies)
  • systat - Statistical tools such as iostat

8. vm-tools & hyper-V

VMWare tools are installed next. Comment this section if not using vmware. An adjacent section for Hyper-V is provided to enable LIS and enhanced session mode.

9. Mail Relay

This section sets up s-nail for sending email via an email relay defined previously. S-nail is the preferred mailer for Ubuntu and provides the same service that mailx does.

10. SNMP (incomplete)

Install snmpd. This section is not finished. The snmpd.conf file must be manually edited.

11. Unattended updates (incomplete)

Ubuntu server installs updates automatically by default. This section must be configured to provide notification and control over the update process. The config files need to be manually edited afterwards as this section still needs some work.

12. Webmin

Webmin is still the best server application administration tool. There are hundreds of plugins for webmin. Cockpit is the best tool for system administration. If you don’t need webmin, comment out these lines. If you do, you may want to consider commenting out the cockpit installation lines to have just one tool.

Next we have the server applications

13. VSFTP

If you need ftp, this is the version to use. The downside is there is no webmin plugin for it. If you really need to administer ftp via webmin, install proftpd instead. If you don’t need an ftp server, comment out this section.

14. MariaDB (MySQL Server)

This will install mariadb server and client and harden the service. This section is interactive.

15. PERL

PERL is required for many web based applications. If not required, comment this section. This section is highly interactive and takes several minutes to install. As well as installing PERL, it installs cpan, cpan minus and numerous perl modules and keeps them updated as much as possible. Error messages in this section are not unusual. Ignore them.

16. Apache

Installs the Apache 2.4 web server. Configuration of httpd.conf is required. Comment out if installing NGINX.

17. PHP for Apache

Installs basic php modules and PEAR. Other modules can be installed by uncommenting as required.

18. NGINX

Installs NGINX instead of Apache.

19. WordPress

Requires Apache. Some heavy editing foo required here or you will be unhappy with the result...

20. phpMyAdmin

If you don't know what this is for, don't install it. 

21. Security evaluation

This section installs security evaluation and reporting tools and prepares a security report for the system.

22. Finish

Final section cleans up and reboots.

The Future

Plans for updates to the post-installation script include:

  1. Make it interactive, so you don’t have to edit the file before running it.

  2. Add logging to file.

  3. Add auto-document capability. This will be the basis for as-built documentation.

  4. Add a silent unattended mode.

The Script

#!/bin/bash
#
# Post installation script for Ubuntu Server 20.04 LTS
#
# Written by Wayne Doust 02 September 2021
#

## Needed for ifconfig to work
apt -y -qq install net-tools

SCTL="/etc/sysctl.conf"
STAMP=`date +%Y%m%d`
SWPP=20
HOST=`hostname -s`
FQDN=`hostname -d`
FQDN=site.local
MAILFWD=<IP of email forwarder>
EMAILINST=installer@$FQDN
EMAILADMIN=admin@$FQDN
SNMPRO=public
SNMPRV=private
SNMPSRV=<IP of SNMP server>
ALLOWFRM="127.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fc00::/7, fe80::/10"
ADDOM=ADdomainname
ADFQDN=ADFQDN
ADUSER=Administrator


IP4="`ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'`"
#IP6="`ifconfig | sed -En 's/::1//;s/.*inet6 (addr:)?(([[:xdigit:]]*::){,4}[[:xdigit:]]*::{,4}[[:xdigit:]]*::{,4}[[:xdigit:]]*::{,4}[[:xdigit:]]*).*/\2/p'`"

###
### The Following section asks for user input to modify some of the above variables
###
clear
echo
echo Ubuntu Server 20.04 LTS Runup Script
echo =========================================================================
echo
echo Enter parameters of this server. Press enter to accept the default.
echo
printf "Hostname [%s]:" $HOST
read ANSWER
if [ "$ANSWER" != "" ]
then
    HOST=$ANSWER
fi
echo Hostname: $HOST

printf "Domain [%s]:" $FQDN
read ANSWER
if [ "$ANSWER" != "" ]
then
    FQDN=$ANSWER
fi
echo Domain: $FQDN

echo Continuing will commence post-installation work of Ubuntu Server
echo ----------------------------------------------------------------
echo
echo Press any key to continue
read ANSWER

### Set Timezone and hostname
## Should use variables here
timedatectl set-timezone Australia/Melbourne
hostnamectl set-hostname $HOST
echo $HOST.$FQDN > /etc/hostname
sleep 3

### Apply updates and install cockpit & optionally pcp
## Note: Whilst you can install both, pick either Cockpit or webmin
##
echo
echo Apply updates
echo
sleep 3
apt -y -qq update && apt -y -qq upgrade
#echo
#echo Installing cockpit
#echo
#sleep 3
#apt -y -qq install cockpit
#apt -y install cockpit-pcp
#systemctl enable cockpit
#systemctl start cockpit

### (Optional) Add server to Actice Directory Domain
echo "deb http://au.archive.ubuntu.com/ubuntu/ bionic universe" >> /etc/apt/sources.list
echo "deb http://au.archive.ubuntu.com/ubuntu/ bionic-updates universe" >> /etc/apt/sources.list
hostnamectl set-hostname $HOST.$ADFQDN
hostnamectl
echo Check Name servers are correct
cat /etc/resolv.conf | grep nameserver
echo
sleep 10
systemctl disable systemd-resolved
systemctl stop systemd-resolved
apt -y update
apt -y install realmd libnss-sss libpam-sss sssd sssd-tools adcli samba-common-bin oddjob oddjob-mkhomedir packagekit
echo
echo Discover AD Domain
echo
realm discover $ADDOM
realm join -U $ADUSER $ADDOM
realm list $ADDOM
pam-auth-update --enable mkhomedir
## Do the following if the previous line doesn't work
#cp /usr/share/pam-configs/mkhomedir /usr/share/pam-configs/mkhomedir.org
#echo "Name: activate mkhomedir" > /usr/share/pam-configs/mkhomedir
#echo "Default: yes" >> /usr/share/pam-configs/mkhomedir
#echo "Priority: 900" >> /usr/share/pam-configs/mkhomedir
#echo "Session-Type: Additional" >> /usr/share/pam-configs/mkhomedir
#echo "Session:" >> /usr/share/pam-configs/mkhomedir
#echo "        required                        pam_mkhomedir.so" >> /usr/share/pam-configs/mkhomedir
#echo "umask=0022 skel=/etc/skel" >> /usr/share/pam-configs/mkhomedir
pam-auth-update
systemctl restart sssd
realm permit $ADUSER@$ADFQDN
realm permit 'Domain Admins' 'sysadmins'
echo "$ADUSER@$ADFQDN    ALL=(ALL)    ALL"          > /etc/sudoers.d/domain_admins
echo "%Domain\ Admins@ADFQDN    ALL=(ALL)    ALL"     >> /etc/sudoers.d/domain_admins
echo "%sysadmins@ADFQDN    ALL=(ALL)    ALL"         >> /etc/sudoers.d/domain_admins

### Optional logging tools based around pcp
## Don't install these unless you know what you're doing
# apt -y install pcp
# systemctl enable pmcd
# systemctl start pmcd
# systemctl enable pmlogger
# systemctl start pmlogger
# systemctl enable pmie
# systemctl start pmie
## use 'pcp atop' 'pmstat' 'pmiostat' etc
## Following is for web API for Grafana
# systemctl enable pmproxy
# systemctl start pmproxy
# wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
# add-apt-repository "deb https://packages.grafana.com/oss/deb stable main"
# apt update
# apt -y install grafana
# systemctl enable grafana-server
# systemctl start grafana-server
# ufw allow 3000/tcp
## Securing Grafana using NGINX Reverse Proxy (more here)
## See https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-grafana-on-ubuntu-20-04

    
### Setup ufw
echo
echo Setting up UFW
echo
sleep 3
ufw default deny incoming
## Allow SSH
ufw allow ssh
ufw limit ssh
## Allow cockpit
#ufw allow 9090/tcp
echo y | ufw enable
ufw status

### Install fail2ban
echo
echo Installing fail2ban
echo
sleep 3
apt -y -qq install fail2ban
#configure fail2ban as required

### Change Swappiness from 60 to 20
## Need to add check for current value in config file
## This could be done better
echo
echo Change swappiness to 20
echo
sleep 3
printf "\nCurrent swappiness="
cat /proc/sys/vm/swappiness
cat $SCTL | grep swappiness | sed -e 's/[^0-9]//g'
echo Current setting=$CSWP
echo Swap Details
echo ------------
swapon --show
sleep 3
printf "\n"
echo 20 > /proc/sys/vm/swappiness
if [ -e $SCTL.org ];
then
    cp -p $SCTL $SCTL.$STAMP;
else
    cp -p $SCTL $SCTL.org;
fi
echo "" >> $SCTL
echo "#Set swappiness to $SWPP" >> $SCTL`
echo "vm.swappiness = $SWPP" >> $SCTL`

### Install useful tools
## wget       - get files via http
## telnet     - telnet client
## bind9utils - utlities for querying dns (such as dig)
## nmap       - network analysis tool
## mlocate    - Faster and more efficient file locator
## mc         - Midnight Commander (XTree like file system interface)
## elinks     - Text based broswer (has dependencies)
## systat     - Statistical tools such as iostat
echo
echo Installing tools
echo
sleep 3
apt -y -qq install wget telnet bind9-utils nmap mlocate mc sysstat
apt -y -qq install elinks

### Install VMware tools if running on VMware
apt -y -qq install open-vm-tools
vmware-toolbox-cmd -v

## ALT: Install Hyper-V LIS if running on Hyper-V
#echo -e "hv_vmbus" >> /etc/initramfs-tools/modules
#echo -e "hv_storvsc" >> /etc/initramfs-tools/modules
#echo -e "hv_blkvsc" >> /etc/initramfs-tools/modules
#echo -e "hv_netvsc" >> /etc/initramfs-tools/modules
#apt -y install linux-virtual linux-cloud-tools-virtual linux-tools-virtual
#update-initramfs -u
## ALT: Install Hyper-V Enhanced Session Mode (xRDP)
## See https://www.kali.org/docs/virtualization/install-hyper-v-guest-enhanced-session-mode/
#apt -y install git
#git clone https://github.com/Microsoft/linux-vm-tools.git ~/linux-vm-tools
#cd ~/linux-vm-tools/ubuntu/
#chmod +x install.sh
#./install.sh
##edit /etc/xrdp/xrdp.ini Change port=vsock://-1:3389 to use_vsock=false
#systemctl enable xrdp.service
#systemctl start xrdp.service
## On host in Admin PS: Set-VM -VMName <vmname> -EnhancedSessionTransportType HvSo

### Setup email relay
echo
echo Setup email relay
echo
sleep 3
apt -y -qq install s-nail
ln -s /usr/bin/s-nail /bin/email
## This next bit could be done better
echo -e "set mta=smtp://$MAILFWD " >> /etc/mail.rc
echo -e "set mailx-extra-rc=/etc/mail.rc" >> /etc/s-nail.rc
echo 'Testing Email relay' | s-nail --subject='Email test 1'  -r "$HOST<$HOST@$FQDN>" $EMAILINST

### Setup SNMP (Not finished)
echo
echo Setup SNMP
echo
sleep 3
apt -y install snmpd snmp
ufw allow snmp
ufw status
#add lines for editing /etc/snmp/snmpd.conf
#change rocommunity public ro6community public etc
#SNMPDOPTS='-LS 0-4 d -Lf /dev/null -p /var/run/snmpd.pid'
cp /etc/snmp/snmpd.conf /etc/snmpd.conf.org
systemctl enable snmpd
systemctl restart snmpd
systemctl status snmpd
snmpwalk -v 2c -c $SNMPRO localhost

### Setup Unattended Updates (Not finished)
echo
echo Setup unattended updates
echo
sleep 3
apt -y -qq install unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades ### Requires intervention
apt-config dump APT::Periodic::Unattended-Upgrade
cat /etc/apt/apt.conf.d/50unattended-upgrades | grep -v '//' | grep '[A-Aa-z]'
apt -y -qq install apt-listchanges
sed -i "/\b\(Unattended-Upgrade\:\:Mail\)\b/d" /etc/apt/apt.conf.d/50unattended-upgrades
echo -e "Unattended-Upgrade::Mail \"$EMAILADMIN\";" >> /etc/apt/apt.conf.d/50unattended-upgrades

### Install Webmin
## If using cockpit, comment this section out
## This also could be done better
echo
echo Installing Webmin
echo
sleep 3
apt -y install wget apt-transport-https software-properties-common
wget -q http://www.webmin.com/jcameron-key.asc -O- | sudo apt-key add -
add-apt-repository "deb [arch=amd64] http://download.webmin.com/download/repository sarge contrib"
apt -y install webmin
ufw allow webmin
ufw limit webmin

###
### Application Section
###

### Install, secure and run MySQL
##
#echo
#echo Installing MariaDB (MySQL)
#echo
#sleep 3
#apt -y install mariadb-server mariadb-client
# alternate install in case the above doesn't work
#apt -y install mariadb-client-10.3
#apt -y install mariadb-server-10.3
# Secure MySQL
#ufw allow mysql
#systemctl start mariadb
#mysql_secure_installation
#systemctl enable mariadb.service

### Install CPAN Minus and update PERL modules (some will fail on dependencies)
echo
echo Installing CPAN and PERL modules (This will take a while and requires interaction)
echo
sleep 5
apt -y install make
apt -y install libnet-ssleay-perl perl-IO-Zlib
cpan App::cpanminus
cpanm Net::FTPSSL
cpanm App::cpanoutdated
cpan-outdated -p | cpanm

### Install Apache web server (needs work)
echo
echo Installing Apache web server
echo
sleep 3
apt -y install apache2
apachectl -v
#<change httpd.conf listen to 0.0.0.0:80>
#be sure to set FQDN
ufw allow http
ufw allow https
ufw status
apachectl graceful
apachectl configtest

### Install PHP for Apache, MySQL and PEAR
echo
echo Installing PHP
echo
sleep 3
apt -y install php php-pear php-mysql
## Enable the following as required: Postgres, ODBC (MS SQL), LDAP, SOAP
#apt -y install php-pgsql php-odbc php-ldap php-soap
## Enable the following to install all PHP related development tools (this is a huge list > 60 packages)
## Only install this on test/dev servers. Don't install on stage, canary or prod servers.
#apt -y install pkg-php-tools
##
echo -e "<?php phpinfo(); ?>" > /var/www/html/info.php
# Test with http://server/info.php
systemctl restart httpd.service
## Setup dedicated Apache2 user

### Install NGINX instead of Apache (Needs lots more work)
#echo
#echo Installing NGINX
#echo
#sleep 3
#apt -y install nginx php php-common php-fpm
## Install as required
#apt -y install php-cli php-json php-pdo php-mysql php-zip php-gd php-mbstring php-curl php-xml php-pear php-bcmath
#ufw allow 'nginx http'
#ufw allow 'nginx https'
#ufw reload
#systemctl stop httpd
#systemctl stop apache2
#systemctl disable --now httpd
#systemctl disable --now apache2
#systemctl enable nginx
#systemctl start nginx  
#nginx -v
#nginx -t
#mkdir -p /var/www/<website>/public_html
#mkdir /var/www/<website>/logs
#chown -R nginx:nginx /var/www/<website>
## edit /etc/nginx/sites-available/default

### Install Wordpress (assumes Apache)
#echo
#echo Installing WordPress
#echo
#sleep 3
#apt -y install php-gd
#systemctl restart httpd.service
#wget http://wordpress.org/latest.tar.gz
#tar xzvf latest.tar.gz
#rsync -avP ~/wordpress/ /var/www/html/
#mkdir /var/www/html/wp-content/uploads
#chown -R apache:apache /var/www/html/*
## Setup WordPress Database
#mysql -u root -p <password>
#CREATE DATABASE wordpress;
#CREATE USER wordpressuser@localhost IDENTIFIED BY 'password'
#GRANT ALL PRIVILEGES ON wordpress.* TO wordpressuser@localhost IDENTIFIED BY 'password';
#FLUSH PRIVILEGES;
#exit
## Configure WordPress
#cd /var/www/html
#cat wp-config-sample.php | sed 's/database_name_here/wordpress/g' | sed 's/username_here/wordpressuser/g' | sed 's/password_here/password/g' > wp-config.php

### Installs phpMyAdmin
#echo
#echo Installing phpMyAdmin
#echo
#sleep 3
#apt -y install php-mbstring php-zip php-gd php-json php-myadmin
#cp /etc/phpMyAdmin/config.inc.php /etc/phpMyAdmin/config.inc.php.orig
## Harden PHPMyAdmin
#cat /etc/phpMyAdmin/config.inc.php.orig | sed -e 's/AllowRoot\'\]\ \=\ TRUE/AllowRoot\'\]\ \=\ FALSE/g' > /etc/phpMyAdmin/config.inc.php  
## Test with http://server/phpMyAdmin

###
### Add security compliance scanning to setup Script for Ubuntu 20.04
###
echo
echo Perform Security Evaluation
echo
sleep 3

##
## Apply updates and install openscap
##
apt -y -qq update && apt -y -qq upgrade
apt -y -qq install libopenscap8
apt -y -qq install ssg-base ssg-debderived ssg-debian ssg-nondebian ssg-applications

##
## Perform default and standard security policy compliance scans for Ubuntu 20.04
##
oscap xccdf eval /usr/share/xml/scap/ssg/content/ssg-ubuntu1604-ds.xml
oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_standard /usr/share/xml/scap/ssg/content/ssg-ubuntu1604-ds.xml

##
## Perform CVE scans
##

snap install cvescan
cvescan -p all
cvescan -p all --show-links > cvescan.out
echo >> cvescan.out
touch cvescan.csv
cvescan --csv -p all > cvescan.csv
## Also add open ports to report
netstat -tulpn | grep LISTEN | grep -v 127.0.0. | grep -v ::1
netstat -tulpn | head -n 2 >> cvescan.out
netstat -tulpn | grep LISTEN | grep -v 127.0.0. | grep -v ::1 >> cvescan.out
echo >> cvescan.out
echo Firewall Status >> cvescan.out
echo >> cvescan.out
ufw status >> cvescan.out
echo >> cvescan.out

##
## Perform OVAL scan and generate report
##
wget -c https://security-metadata.canonical.com/oval/com.ubuntu.$(lsb_release -cs).usn.oval.xml.bz2
bunzip2 com.ubuntu.$(lsb_release -cs).usn.oval.xml.bz2
oscap oval eval --report report.html com.ubuntu.$(lsb_release -cs).usn.oval.xml
## Email the report
cat cvescan.out | s-nail --subject="Security Report for $HOST" -a report.html -a cvescan.csv -r "$HOST<$HOST@$FQDN>" $EMAILINST

##

## Remove security eval prodcuts
##
echo
echo Removing security scan software
echo
sleep 3
snap remove cvescan
apt -y -qq remove libopenscap8

###
### Finish installation
###
echo
echo Cleanup installation and reboot
echo
sleep 3
apt -y -qq update && apt -y -qq upgrade
apt -y -qq autoremove --purge
echo
echo Rebooting in 60 seconds
echo
sleep 10
shutdown -r +1 Server Rebooting in 1 minute
echo
echo
sleep 60

Tuesday, 9 November 2021

Configuring Evolution-EWS to connect to Exchange Online

Let me quickly get something off my chest:

I hate MS Exchange. 

I loathe it. There are few things I despise more. 

I would prefer almost any other integrated messaging system than it. The reasons why are far too long to go into here. It really deserves its own blog entry - which I may do some day.

Unfortunately, unless you are the decision maker for the organisation for which you work, or at least hold some good sway with your IT Steering Committee. You are probably stuck with it.

If your organisation is like most, you are probably migrating to Office 365 or have already done so. If Linux is your primary or preferred platform and you want to be able to receive your email, calendar etc. on your Linux desktop, this may be something of a problem. So, here's my explanation of how to use Evolution as your messaging client for Exchange Online using Exchange Web Services via evolution-ews.

What is "Exchange Web Services" (and why should I care)?

Exchange Web Services (EWS) is an application program interface (API) that allows programmers to access Microsoft Exchange items such as calendars, contacts and email. 

EWS first became available in Exchange Server 2007. It provides the ability to store, retrieve, move and modify email and related data for a single user, a group of users or an entire Exchange Server organisation on an Exchange server. EWS can be used to migrate Exchange data on-prem or to a third-party host in the cloud, or simply as an interface for a mail app or messaging client. Previously, if you wanted to do this you had to leverage Outlook Web Access (OWA).

As well as being available for On-prem editions of Exchange, EWS is available for Office 365, however that access is slightly different.

Evolution-EWS

Evolution-ews from 3.27.91 on has had the capability of connecting to office 365 with OAuth2 authentication. The administrator of the account must allow access via this method. Fortunately this is the default, so I suggest you don't mention it to your Exchange administrator as they may decide to block access.

Users of free accounts at live.com/hotmail.com/outlook.com addresses can also configure EWS account with the same Host URL, but they cannot use OAuth2, it's required to create an application specific password. Organisation accounts can use application specific passwords too, but administrators can disable this feature.
There are two existing application IDs, but the organisation administrators can create their own application and have everything under their control.

To be able to use OAuth2 with outlook.office365.com server an Application ID, which identifies the application which requests access to user data, and a Tenant ID, which basically identifies the organisation, are required.

First make sure everything is installed:

Ubuntu/Debian Instructions

sudo apt-get remove evolution
sudo apt-get update
sudo apt-get install evolution
sudo apt-get install evolution-ews

Note that the first line is there to remove the old version - which may not be up to date. This may not be necessary for you but YMMV.

CentOS/RedHat/Rocky instructions

sudo yum update
sudo yum install evolution
sudo yum install evolution-ews

If you are using DNF, replace 'yum' with 'dnf'

Finding your Tenant ID

Each organisation has assigned its directory (tenant) ID, which is used to identify the organisation when authenticating the user. How to find out the tenant ID is described here. A short walk-through is:

  1. login to https://portal.azure.com

  2. click the View button below Manage Azure Active Directory near the top of the page

  3. the Overview section (selected by default) shows a Tenant information where is the Tenant ID

It can be seen also when:

  1. login to https://portal.azure.com

  2. click the View button below Manage Azure Active Directory near the top of the page

  3. pick App registrations subsection

  4. click Endpoints at the top of the subsection

It opens a table, where can be seen OAuth 2.0 authorization endpoint (v2) and OAuth 2.0 token endpoint (v2). Evolution-ews uses

https://login.microsoftonline.com/$TENANT/oauth2/token

and

https://login.microsoftonline.com/$TENANT/oauth2/authorize
,

where the $TENANT is replaced with the same value as the Tenant ID from the above.

If you are a normal user and do not have the required permission to check in the portal.azure.com, you might find the tenant ID in your browser history. Search for URLs containing tenantId=........-....-....-....-.............

Copy this Tenant ID, it'll be used together with Application ID when configuring evolution-ews.

Choosing an Application ID

There are two unverified applications (for testing purposes). They are setup in a way that they can be used by the organisations, though, depending on the organisation settings, the administrators may or may not need to approve them first. These applications can be used with the organisation tenant ID or with the common (or left empty) tenant ID. Again, it depends on the actual organisation settings. 

  1. 20460e5d-ce91-49af-a3a5-70b6be7486d1 - has both EWS and Microsoft Graph API usages enabled, but the Graph API is not enabled (in evolution-ews 3.38.x) due to its incompleteness. The application identifies itself as GNOME Evolution. It's preferred in case the Graph API would be used in the future, thus the transition to it will be smooth.

  2. 751cf8be-ca07-484b-9308-fac4b9d85eff - has only the EWS protocol enabled. The application identifies itself as GNOME Evolution EWS.

  3. Users can also try application IDs shown at point 12 of this Microsoft page, like d3590ed6-52b3-4102-aeff-aad2292ab01c or ea5a67f6-b6f3-4338-b240-c655ddc3cc8e, with the Redirect URI set to urn:ietf:wg:oauth:2.0:oob and other values kept empty.

If your organisation has its own Application ID, use that one. If you are the administrator for your organisation, and want to create your own Application ID by following this link.

Evolution Instructions

Launch the Evolution application. If this is a new installation, follow the prompts below to configure your account. Otherwise, select the menu items File -> New -> Mail Account, click Next, then follow the prompts.

  • Enter your name and your primary SMTP address, uncheck Look up mail server details… and click Next
  • For Server Type, select Exchange Web Services
  • For Username, specify your email address
  • Change Host URL to https://outlook.office365.com/EWS/Exchange.asmx
    Click the Fetch URL button, providing your EID password when prompted. (If this doesn't work, don't worry, it can be done later). This will result in the OAB URL field being populated, which is the address from which the client can download a copy of the Offline Address Book.
  • Change Authentication to OAuth2 (Office365).
  • Make sure that Override Office365 OAuth2 settings is checked and populate the Tenant ID and Application ID fields as follows:
    • Tenant ID: your tenant ID
    • Application ID: choose from above
  • Finish the New Mail Account Wizard, and you will then be taken to the University’s login page. Authenticate with your EID credentials and perform Duo multi-factor authentication.

Configuring Evolution-EWS to connect to Exchange Online

Please note that the initial synchronization with your account may take an extended period of time if you have a large mailbox.

If you've used EWS previously, you would have noticed that credential management is handled by the Gnome settings under online accounts. With O365 this does not happen. I'm not sure why it's different - it may have something to do with how the data is presented via the App ID, but I'm only guessing here. If anyone knows, please enlighten me in the comments.

Acknowledgements

The following links were helpful to me and acted as source material:

https://sites.utexas.edu/glenmark/2021/02/01/how-to-setup-your-office-365-email-using-evolution-ews-linux/

https://wiki.gnome.org/Apps/Evolution/EWS/OAuth2

https://bugzilla.redhat.com/show_bug.cgi?id=972562

Sunday, 25 April 2021

CentOS 7 post installation script

automatic basic server runup tasks

I like automation. Anything I can do to speed up repetitious tasks is worth the effort. The following shell script is a work-in-progress. Each time I run up a server, I use this script to automate the post installation tasks. I just uncomment the sections I need and run the script. Parts of it take some time and require some human intervention, but usually that just involves pressing 'enter' a few times. The script doesn't do much in the way of hardening the server - that's the stuff of another blog entry.

To use the script, cut and paste it into an editor, make it executable and run it as root. Unfortunately sudo doesn't cut it for some steps. Make sure you uncomment the sections you need first. There are modifications in there for RHEL if you're using that instead of CentOS. I have created a version for CentOS 8, but the it now EOL at the end of this year, I figure it's a little pointless. If anyone wants it, just ask and I'll make it available.

Briefly, the script does the following things:
  1. Runs a yum update using deltas
  2. Adds the epel repository and optionally the remi repository
  3. Installs selinux utilities
  4. Installs PERL, CPAN and useful utilities for PERL.
  5. Installs Apache or NGINX
  6. Installs php for apache
  7. Optional upgrade for php 5.6 
  8. Installs webmin
  9. Installs vsftpd
  10. Installs and secures mysqld
  11. Installs vmtools
  12. Installs miscellaneous utilities
  13. Configure to remove old kernels automatically
  14. Setup email forwarding
  15. Setup and configure WordPress
As I runup more servers with different services, I will update and expand the script. I'm currently writing a GUI front end for the script in Xojo (see below) to customise and generate the script for any environment. If it works, I hope to expand it to include the ability to deploy the script remotely as well as generate it.
 


#!/bin/bash
## The following commands increase the number of packages available
##
yum -y update
yum -y install deltarpm
yum -y install epel-release
## Uncomment for REMI
# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
# yum --enablerepo=remi,remi-test

yum repolist
yum -y update

## RHEL instructions
# wget http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-10.noarch.rpm
# rpm -ivh epel-release-7-10.noarch.rpm
# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
# yum --enablerepo=remi,remi-test
# yum repolist
# yum -y update

## Install SELinux utilities
##
yum -y install policycoreutils policycoreutils-python selinux-policy selinux-policy-targeted libselinux-utils setroubleshoot-server setools setools-console mcstrans

## Install PERL and useful modules and utilities via cpan and cpanm
##
yum -y install perl perl-Net-SSLeay perl-IO-Zlib openssl perl-IO-Tty cpan
cpan App::cpanminus
cpanm Net::FTPSSL
cpanm App::cpanoutdated
cpan-outdated -p | cpanm
cpan-outdated -p | cpanm

## Install and start Apache Web server.
##
yum -y install httpd
#<change httpd.conf listen to 0.0.0.0:80>
systemctl enable httpd.service
systemctl start  httpd.service
systemctl status httpd.service
firewall-cmd --zone=public --permanent --add-service={http,https}
systemctl restart firewalld.service
firewall-cmd --list-all
apachectl graceful
apachectl configtest

## Install NGINX
##
# echo -e "[nginx]\nname=nginx repo\nbaseurl=http://nginx.org/packages/centos/$releasever/$basearch/\ngpgcheck=0\nenabled=1" > /etc/yum.repos.d/nginx.repo
# yum -y install nginx php php-common php-fpm
# firewall-cmd --zone=public --permanent --add-service={http,https}
# systemctl stop httpd
# systemctl disable httpd
# systemctl enable nginx
# systemctl enable php-fpm
# systemctl start nginx
# systemctl start php-fpm
# mkdir -p /srv/www/<website>/public_html
# mkdir /srv/www/<website>/logs
# chown -R nginx:nginx /srv/www/<website>

## Install PHP for Apache, mysql and MSSQL
##
yum -y install php php-pear  php-mysql
## Enable the following as required
# yum -y install php-pgsql php-odbc php-mssql php-ldap php-soap
# yum -y install phpmyadmin httpd-tools
# cp /etc/phpMyAdmin/config.inc.php /etc/phpMyAdmin/config.inc.php.orig
# Harden PHP
# cat /etc/phpMyAdmin/config.inc.php.orig | sed -e 's/AllowRoot\'\]\ \=\ TRUE/AllowRoot\'\]\ \=\ FALSE/g' > /etc/phpMyAdmin/config.inc.php

## Test with http://server/test.php
## Test with http://server/phpMyAdmin

## Upgrade to PHP 5.6 (optional)
##
#rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
#yum repolist
#yum -y remove php-common
#yum -y update
#yum -y install php56w php56w-opcache php56w-xml php56w-mcrypt php56w-gd php56w-devel php56w-mysql php56w-intl #php56w-mbstring
#systemctl restart httpd.service
#php -v

systemctl restart httpd.service
echo -e "<?php phpinfo(); ?>" > /var/www/html/info.php
systemctl restart httpd.service

## Install and run Webmin administration (requires PERL)
##
echo -e "[Webmin]\nname=Webmin Distribution Neutral\nbaseurl=http://download.webmin.com/download/yum\nenabled=1" > /etc/yum.repos.d/webmin.repo
rpm --import http://www.webmin.com/jcameron-key.asc
yum -y install webmin
systemctl enable webmin.service
systemctl start  webmin.service
systemctl status webmin.service
firewall-cmd --zone=public --permanent --add-port=10000/tcp
firewall-cmd --reload
firewall-cmd --list-all

## Install and start VSFTPD
##
#yum -y install vsftpd ftp
#systemctl enable vsftpd.service
#systemctl start vsftpd.service
#firewall-cmd --zone=public --permanent --add-service=ftp
#systemctl restart firewalld.service
#firewall-cmd --list-all

## Install, secure and run MySQL
##
#yum -y install mariadb-server mariadb
#systemctl start mariadb
#mysql_secure_installation
#systemctl enable mariadb.service
#systemctl status mariadb.service

## Install tools for vmware
##
yum install open-vm-tools
vmware-toolbox-cmd -v

## Install Misc utilities as desired
##
yum -y install wget telnet bind-utils nmap mlocate mc
yum -y install elinks

## Remove old kernels and set yum to preserve only two. Setup auto updates
##
yum -y install yum-utils yum-cron
package-cleanup -y --oldkernels --count=2
echo -e "\ninstallonly_limit=2\n" >> /etc/yum.conf
#yum -y install yum-cron # edit /etc/yum/yum-cron.conf or do this via webmin instead on yum-cron
#systemctl start yum-cron
#systemctl enable yum-cron

## Setup email forwarding
##
yum -y install mailx
ln -s /bin/mailx /bin/email
echo -e "set smtp=smtp://<mail forwarding ip address> " >> /etc/mail.rc


## Install Wordpress
#yum -y install php-gd
#systemctl restart httpd.service
#wget http://wordpress.org/latest.tar.gz
#tar xzvf latest.tar.gz
#rsync -avP ~/wordpress/ /var/www/html/
#mkdir /var/www/html/wp-content/uploads
#chown -R apache:apache /var/www/html/*


## Setup WordPress Database
#mysql -u root -p <password>
#CREATE DATABASE wordpress;
#CREATE USER wordpressuser@localhost IDENTIFIED BY 'password'
#GRANT ALL PRIVILEGES ON wordpress.* TO wordpressuser@localhost IDENTIFIED BY 'password';
#FLUSH PRIVILEGES;
#exit

## Configure WordPress
#cd /var/www/html
#cat wp-config-sample.php | sed 's/database_name_here/wordpress/g' | sed 's/username_here/wordpressuser/g' | sed 's/password_here/password/g' > wp-config.php

Wednesday, 21 April 2021

Broken YUM on CentOS 7 (or how I learned to love DNF)

Yellowdog Update Modified

It's a simple thing to keep your system updated. A quick yum update every few days - just like brushing your teeth. Completely painless, quick, efficient.

Not today it wasnt.

---> Package screen.x86_64 0:4.1.0-0.26.20120314git3c2946.el7 will be updated
---> Package screen.x86_64 0:4.1.0-0.27.20120314git3c2946.el7_9 will be an update
---> Package skypeforlinux.x86_64 0:8.67.0.96-1 will be updated
---> Package skypeforlinux.x86_64 0:8.71.0.36-1 will be an update
Error: Invalid version flag: or

This was the error I received. Okay, so when yum update fails, there's always the tried and true command sequence that fixes it:

sudo yum clean all
sudo yum update --skip-broken

This time it didn"t work. I still received the same error. Time to google for more info... 

I found a kool command sequence on John S. De Stefano's blog that looked promising:

sudo yum check all                # tells you of any problems
sudo package-cleanup --problems   # lists all known package problems
sudo package-cleanup --dupes      # lists duplicate packages
sudo package-cleanup --cleandupes # actually cleans up duplicates
sudo yum check all                # run again to check for remaining problems
sudo yum-complete-transaction --cleanup-only

However, this command sequence failed to fix the issue too. Looks like I'm going to have to work out what's broken and why. No easy way out with this problem.

Rich Dependencies

Scrolling through bugzilla, I found the following entry:

There was a mistake made in the rpmlib() dep for rich deps. You need
at least rpm 4.13 for the base rich deps, and rpm 4.13.1 for the rest.

yum and related packages are no longer actively developed.
They are being replaced with dnf, dnf-utils, etc.

I'm closing this bug because it's most likely never going to be fixed.
If you still consider your bug report important, reopen it, please.
https://bugzilla.redhat.com/show_bug.cgi?id=1578942

This was actually a bug report for F28+. Since Fedora uses DNF primarily and YUM is deprecated, no one seemed particularly interested in fixing it in Fedora. RHEL/CentOS 8 both use DNF as well. Could this bug have percolated down into CentOS 7? Time to check rpm versions and make sure I have at least 4.13:

$ yum --showduplicate list rpm

Installed Packages
rpm.x86_64                          4.11.3-45.el7                          @base
Available Packages
rpm.x86_64                          4.11.3-45.el7                          base 

Well, that's just peachy!

I'm running an old version of rpm that doesn't support rich dependencies. It also appears that yum may not handle them well either - although the indications are the problem really lies with rpmlib().

I've never really spent a lot of time looking at the inner workings of package managers and their respective update managers. Now that ignorance is coming back to haunt me and it's time for some old fashioned studying the matter.

From rpm.org there's an excellent description of how the boolean operators work and how they help avoid dependency hell. This is what is being referenced in the error I received. The 'or' operator is unknown because my version of rpm is too old. Boolean operators enable what is termed "rich dependencies". Basically providing a logical sequence for resolving dependency issues across multiple versions. A good example is community-mysql and mariadb. Both packages do the same thing - provide a mysql style database. Without rich dependencies, if another package requires mysql, you have to choose which package is required. With rich dependencies you can state:

Package A: Requires: mysql
Package mariadb: Provides: mysql
Package community-mysql: Provides: mysql
Suggests: mariadb to Package A.

Which means that if community-mysql is already installed, that is used as the dependency, otherwise mariadb is installed.

This is really cool, but yum simply ignores it.

Put simply, the root cause of the problem is:

1. RPM supports "rich dependencies"
2. DNF supports resolving packages with "rich dependencies"
3. YUM does not support resolving packages with "rich dependencies"

The solution then is obvious: Since CentOS 7 supports DNF, it's time to switch. Fiddling with yum and manually resolving the dependencies will only delay the inevitable.

YUM vs DNF 

source

"Dandified YUM" or DNF, is the replacement package update manager for RHEL/CentOS. It's been part of Fedora for a long time now. I acknowledge it is clearly superior to YUM in most aspects, plus it doesn't suffer from some of the issues that Debian apt does. The major goal is to eliminate (where possible) dependency hell. But it also has other advantages.

It was also designed to be as drop-in replaceable to yum as possible. It comes very close, but some commands have no equivalent (some of these are deliberate actions). So, for me, if your used to using yum, dnf just represents yet another sequence of commands that must be memorised just to continue doing your job.

I'm not going to bore you with lists here of features, commands, comparisons etc. The links I've provided do that well enough. Plus, if you want a deep dive into dnf, you can go here. Suffice it to say that I decided that installing and using dnf was the simplest and most effect potential solution to the immediate and potentially long term problems.

Install DNF on CentOS7

Pretty simple really, however there are a number of dependencies since it leverages by Py2 and Py3. A total of 11 dependent packages were installed, however YMMV.

$sudo yum install dnf
...
Resolving Dependencies
--> Running transaction check
---> Package dnf.noarch 0:4.0.9.2-2.el7_9 will be installed
--> Processing Dependency: python2-dnf = 4.0.9.2-2.el7_9 for package: dnf-4.0.9.2-2.el7_9.noarch
--> Running transaction check
---> Package python2-dnf.noarch 0:4.0.9.2-2.el7_9 will be installed
--> Processing Dependency: dnf-data = 4.0.9.2-2.el7_9 for package: python2-dnf-4.0.9.2-2.el7_9.noarch
--> Processing Dependency: python2-libdnf >= 0.22.5 for package: python2-dnf-4.0.9.2-2.el7_9.noarch
--> Processing Dependency: python2-libcomps >= 0.1.8 for package: python2-dnf-4.0.9.2-2.el7_9.noarch
--> Processing Dependency: python2-hawkey >= 0.22.5 for package: python2-dnf-4.0.9.2-2.el7_9.noarch
--> Processing Dependency: libmodulemd >= 1.4.0 for package: python2-dnf-4.0.9.2-2.el7_9.noarch
--> Processing Dependency: python2-libdnf for package: python2-dnf-4.0.9.2-2.el7_9.noarch
--> Processing Dependency: python-enum34 for package: python2-dnf-4.0.9.2-2.el7_9.noarch
--> Running transaction check
---> Package dnf-data.noarch 0:4.0.9.2-2.el7_9 will be installed
---> Package libmodulemd.x86_64 0:1.6.3-1.el7 will be installed
---> Package python-enum34.noarch 0:1.0.4-1.el7 will be installed
---> Package python2-hawkey.x86_64 0:0.22.5-2.el7_9 will be installed
--> Processing Dependency: libdnf(x86-64) = 0.22.5-2.el7_9 for package: python2-hawkey-0.22.5-2.el7_9.x86_64
--> Processing Dependency: libsolvext.so.0(SOLV_1.0)(64bit) for package: python2-hawkey-0.22.5-2.el7_9.x86_64
--> Processing Dependency: libsolv.so.0(SOLV_1.0)(64bit) for package: python2-hawkey-0.22.5-2.el7_9.x86_64
--> Processing Dependency: libsolvext.so.0()(64bit) for package: python2-hawkey-0.22.5-2.el7_9.x86_64
--> Processing Dependency: libsolv.so.0()(64bit) for package: python2-hawkey-0.22.5-2.el7_9.x86_64
--> Processing Dependency: librepo.so.0()(64bit) for package: python2-hawkey-0.22.5-2.el7_9.x86_64
--> Processing Dependency: libdnf.so.2()(64bit) for package: python2-hawkey-0.22.5-2.el7_9.x86_64
---> Package python2-libcomps.x86_64 0:0.1.8-14.el7 will be installed
--> Processing Dependency: libcomps(x86-64) = 0.1.8-14.el7 for package: python2-libcomps-0.1.8-14.el7.x86_64
--> Processing Dependency: libcomps.so.0.1.6()(64bit) for package: python2-libcomps-0.1.8-14.el7.x86_64
---> Package python2-libdnf.x86_64 0:0.22.5-2.el7_9 will be installed
--> Running transaction check
---> Package libcomps.x86_64 0:0.1.8-14.el7 will be installed
---> Package libdnf.x86_64 0:0.22.5-2.el7_9 will be installed
---> Package librepo.x86_64 0:1.8.1-8.el7_9 will be installed
---> Package libsolv.x86_64 0:0.6.34-4.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

Next I tried dnf update:

$ sudo dnf update
<snip>
Running transaction check
Error: transaction check vs depsolve:
(libatomic or libatomic1) is needed by skypeforlinux-8.71.0.36-1.x86_64
rpmlib(RichDependencies) <= 4.12.0-1 is needed by skypeforlinux-8.71.0.36-1.x86_64
To diagnose the problem, try running: 'rpm -Va --nofiles --nodigest'.
You probably have corrupted RPMDB, running 'rpm --rebuilddb' might fix the issue.
The downloaded packages were saved in cache until the next successful transaction.
You can remove cached packages by executing 'dnf clean packages'.

DNF is smart enough to know why the update failed. The package 'skypeforlinux' uses rich dependencies. These dependencies require a version of rpmlib that is greater than the CentOS 7 repositories can provide. Therefore, the dependencies cannot be resolved. There's a tip there to use rpm directly to reconcile the issues, but since I know that the version of rpm is also too low, that won't work.

I decide that I can live without skypeforlinux, so I remove it and both dnf and yum are happy.

At this point in time, since both work, I can use either to keep my system updated. However, having installed dnf and now that I'm comfortable working with it (having learned the syntax and equivalent commands) I think I'll use it from now on.

Tuesday, 20 April 2021

How SORBS ruined my life (old blog)

When this blog entry was written, Open Relay blockers like SORBS were considered the primary defence mechanism against spam email. They are still often used, but not as much as they used to be - for many of the reasons discussed in this article. SPF, DKIM & DMARC have largely taken their place.
 
SORBS (SPAM and Open Relay Blocking System)
 
I've had a helluva week so far, and I've got SORBS to thank for it.

SORBS (Spam and Open Relay Blocking System) is an email server reputation service. It (along with other reputation services) collect data on servers that are are either poorly configured (and open to abuse) or actively send spam. Reputation services are an excellent way of protecting against spam. They have very high hit rates and (generally) very low false positives. They also have a very low performance overhead compared with heuristic and bayesian filtering techniques. The mail servers I admister are configured to quarantine all email that is listed by either SORBS, SpamHaus or SpamCop (two other reputation services).

However, sometime last week (when I was off work sick), SORBS listed pretty much all of the hotmail, windows live, yahoo, bigpond, optusnet and myplace servers. There may have been others listed as well.

Responding to a few complaints that came in on Monday about email not being received, I began checking. Then began the sinking feeling that goes along with knowing that I'd have to change the email filtering rules, do some regression tests and then resubmit a week's work of spam through the email filters. SORBS is a very aggressive filter and I've been quite reliant on it for some time.

Less fun was trying to explain the problem to the CEO.

The first part of the quick fix was to move the SORBS check to the end of the anti-SPAM rules of the DMZ mail filter and set it to monitor only - not block. The DMZ mail server is exposed to the Internet and performs basic/quick checks only and does not look at the content of the email messages. It is highly robust and is meant as the front line of defence. It experiences an average of 90 security attacks per hour. It filters about 75% of the email traffic as inappropriate before passing the "possibly okay" messages to the second filter.

The second part was to add a check for zero day threats on the DMZ server and tag messages accordingly.

The third part was to tighten the screws a bit on the second mail filter. This meant decreasing the tolerance limits a little and added a few more checks which included looking for the tags on the email messages placed there by the DMZ mail filter. Usually, this server intercepts about 8% of messages pass to it. Messages quarantined by this server may result in a quarantine message and even a self-release option depending upon the spam score the email receives.

Now that these changes were made, I resubmitted 2143 spam quarantined messages. With the new rules in place, 1963 messages were blocked and 180 passed through to the second filter which blocked a further 68 messages leaving 112 messages sailing through to the mail server. I don't know how what the spam:ham ratio of the 112 messages was but the count seemed to be manageable so I released the remaining 14,000 quarantined messages and sent an email instructing people to forward any received spam to the spam submit mailbox for heuristic analysis. So far, I have 35 spam messages submitted by users which (if accurate) we now have a spam hit rate of 99.75% with (hopefully) a close to zero false positive rate. The hit rate has dropped to 59.4% for the DMZ server and risen to 12.5% for the second filter. Time and monitoring will determine how successful the changes have been.

Moving forward, I have written replacement rules that will no longer quarantine email based upon failed reputation. The new rules will look at SPF (Send Policy Framework - RFC4088) in addition to reputation. If the SPF check passes, the email will be accepted. If SPF fails, it will be dropped. If SPF is 'softfail' or 'none' then it will be subject to a reputation check. Any failure will drop then connection with a 46x error - Temporary Failure, with details as to why sending failed. The sending MTA will then notify the recipient that the email failed to send. The sending server then has the option of implementing SPF. I'd like at some point to add a DKIM check, but that's a reasonably difficult task.

BTW, I am heavily influenced by Ming Weng Wong's whitepaper on Messaging Anti-Abuse:

 
 

Monday, 19 April 2021

Why is Backup so hard?

Performing a backup never used to be hard, in fact, it used to be the easiest job a sysadmin could perform. So, the ever present question many sysadmins end up asking is: Why is something that used to be so easy, now so difficult? The next equally valid question is:

Why is it also so EXPENSIVE?

As with most things, we are dealing with a history lesson.

In the early days of mainframes, you dealt with a monolithic system. Everything (and I mean everything!) came from a single vendor - and that included a backup system.

How the backup system actually worked was never much of a question. It just worked OOTB (Out Of The Box). Despite this, there was a reasonable degree of busy work involved. In fact, the primary job of the sysadmin was backups.

Consider the situation: You have several rows of IBM 72x TBUs all purring away madly. Now the tape software may know what tape it is writing to, but these are reel-reel tapes. There are no barcode labels to be read and no link between the media header on the tape and what you write on the tape (and it's box). You have to be super organised. A bell (literally a bell!) will go off on the operator console, you read the message to remove tape xyz01 from TBU 23 and replace it with tape qwe12 etc. So you run around like a blue-assed fly to make sure the tapes are properly stored in sequence and you know where all the catalog tapes are just in case the storage decides to die - a not uncommon occurrence.

In fact, in days of very expensive storage, tape was considered the mainstay. Several units were often dedicated for "offline" and "standby" storage. The only difference between the two was that standby storage was on tapes that hadn't been removed yet. Often the TBUs would double up - standby during the day and backup operation at night. Tape was cheap, disk was expensive.

The popularity of UNIX destroyed proprietary backup systems. On a UNIX system, a TBU was just another device to be written to or read from. The 'tar' utility (Tape ARchiver) turned one an entire subdirectory structure into a single file for writing (or reading from) a tape device. For raw block level backups of a disk volume, "dump" and "restore" were popular from early days of UNIX. All of these commands were frequently used in script. Sysadmins developed their own scripts and cronjobs. Usually, very little effort was put into documenting these scripts. The sysadmin 'knew' what was going on - and that was all that mattered.

As the desktop computer began pushing into the business computer market, initially little thought was put towards backups. You made copies of floppies and if you were lucky enough to have a hard disk drive, you just manually copied files onto floppy disk. Some early backup systems began to appear like Fastback which offered full duplex support and compression.

As the size of desktop computer HDDs increased, the ability to 'back up to floppy' dropped off considerably. Once again, proprietary backup systems began to appear. One of these was the 4mm Colorado Jumbo, which was an inexpensive TBU that connected to the FDD interface - meaning a separate controller did not need to be purchased. Colorado bundled some backup software - but it wasn't particularly good.

Around this time, Novell Netware 2 and later Netware 3.12 was increasing in popularity. Vendors would sell Netware 5 user version and install it on a glorified workstation. It was common to install either a Colorado Jumbo TBU or a more expensive QIC TBU. The latter would require a SCSI card. 

However, Netware didn't have a native backup software.

About the only backup software that was available for Netware was ArcServe. 

It was horrible.

Sure, it wasn't too bad at backing up your files. It just a hard time restoring them. It also had a habit of crashing servers. On Netware this was called an ABEND. Pretty soon, people the idea of setting up a dedicated backup server, so if the backup server crashed, it wasn't too bad. People also found that particular SCSI cards and TBUs caused Arcserve to be more stable than others. Particular servers were also kinder. Unfortunately, this "stability" came at a price.

Arcserve wasn't too expensive - which was its only real saving grace. The other was the complete lack of any alternative. When Windows NT came out, Arcserve made a version for it - which managed to port all the same stability problems to the new platform.

Then came Backup Exec. It was a breath of fresh air! Simple. Stable. Affordable.

Okay, it was more expensive, but you didn't need a dedicated backup server. In fact, there was a cut down version that came with a SCSI card and a Colorado Travan TBU. It all worked out of the box for under $500! Overnight, pretty much everyone switched to Backup Exec.

Successive versions added more options: open file, DR, Groupwise, BTree, NDS, Windows, Unix, Linux. However the stability gradually fell away. It was still good, but the dedicated backup server was resurrected. The price increased too. It doubled, then tripled. Soon, the best thing you could really say about Backup Exec was that it was better than ArcServe - which by now had been purchased by Computer Associates and was called ArcserveIT.

Veritas (who owned Backup exec) spawned another backup product very similar to Backup Exec - Netbackup. It became the standard for heterogeneous backup. To celebrate this, they added a zero on the price tag.

Netbackup Management Console

Then came a sequence of enterprise backup products. They were all better than Backup Exec. More stable. Heterogeneous. Great support. Agents for everything you could imagine. Policy based. But by this time, they cost in the tens of thousands of dollars.

They were Syncsort, CommVault, HP Data Protector, Portlock. No sooner did one product come out, but another did that was better with extra features. 

Then the game changer of them all came out: Veeam.

It was like Backup Exec all over again. Relatively cheap. designed primarily for virtual machines, it could do what all the others struggled with: Restore a complete working server in minimal time. 

Pretty soon, Veeam became the dominant backup software. It was a little feature poor at first, but you could do cloud based backup - meaning you didn't need to buy expensive tapes or TBUs. Veeam charged very little for cloud storage.

Slowly, as successive versions of Veeam came out, features were added. However costs began to go up again and reliability and stability began to drop. Veeam also started increasing the cost of cloud restore operations - so whilst backing up to the cloud was cheap, restoring from it cost a fortune!

Now, organisations using Veeam are casting around for alternatives. There's  EMC Networker, Altaro, Nakivo plus there are appliance based systems like Datto that work on a different paradigm. They all have one thing in common:

They are very expensive.

The goal seems to be to create hassle free simple backups. Over time, software companies sem to forget that and overload their software with Netfeatures few people use.

It seems to me the solution is to create a two tier system: the simple software that always works and the heterogenous one that deals with all of the weird and wonderful situations. 

That sounds like a simple solution, unfortunately it's always the low cost product that makes the profits and drives innovation. And nobody wants to run two pieces of software. This means the larger business that pay the most for your product, don't use the cheaper versions. When Backup Exec came out, all the large organisations stuck with ArcServe. The same is true of Veeam. Netbackup continues to hold sway in larger organisations. A quick persual of the Netbackup support forums gives the distinct impression that those who administer NetBackup have only one job to do: Backup support. If that's your only job, you don't really care that much if it's difficult to administer and requires arcane knowledge and sophisticated scripting skills. It also doesn't matter that it's hyper-expensive. In fact, that expense is a good thing as it masks you salary in the TCO.

So, I fear history is doomed to continually repeat itself. Think about that the next time a new piece of backup software appears on the market that seems too good to be true.