Nov 20, 2012

Clearing orphaned and unused packages from CentOS 6.3


This is a follow on post from my guide to installing CentOS 6.2 (or you can read my updated 6.3 version) and auditing your software installs. We will go through some of the steps required to secure your server and get it ready for production use.

As always, I suggest you take this time to tighten up your machine first; run updates, turn off services, install software and harden your machine. You should also consider setting up your SSH settings.

To check which packages are left on your system just run the following command:
package-cleanup --leaves --exclude-bin
(NOTE: The --exclude-bin option means that packages with bin files are not included; to see packages with bin files just delete the option)

If you are happy with the list produced, run the modified version to delete all the files:

package-cleanup --quiet --leaves --exclude-bin | xargs yum remove -y

Further Reading

Nov 18, 2012

Setting up a CentOS 6.2 web server: Accounts Hardening

This is a follow on post from my guide to installing CentOS 6.2 and auditing your software installs. We will go through some of the steps required to secure your server and get it ready for production use.

These steps will outline how to harden your user accounts to lessen the risk that they will be compromise (and limit the damage able to be done if they are compromised).
We will assumes you have already created a new user account; if you haven't, just run the following command:

adduser -m -U USERNAME
passwd USERNAME

Now let's lock down our accounts!
  1. Let's restrict the root access to the system console only. Edit /etc/securetty and remove everything except for the following:
    console
    tty1
    tty2
    ...
    tty10
    tty11
  2. Uncomment the following line in /etc/pam.d/su

    auth required pam_wheel.so use_uid

  3. Uncomment the following line in /etc/sudoers

    %wheel ALL=(ALL) ALL
  4. Add your new administrator user to the wheel group
    usermod -G wheel USERNAME
  5. Now we will lock non-root system accounts and block shell access. Figure out the list of accounts by running the following (it will print a list of accounts with the associated UID):
    awk -F: '{print $1 ":" $3 ":" $7}' /etc/passwd
  6. Run the following commands on any non-root account with a UID less than 500:
    usermod -L account
    usermod -s /sbin/nologin account
     
  7. For reference, this is a list of system accounts generally created on a fresh install:
    bin
    daemon
    adm
    lp
    sync
    shutdown
    halt
    mail
    uucp
    operator
    games
    gopher
    ftp
    nobody
    dbus
    rpc
    abrt
    vcsa
    haldaemon
    saslauth
    postfix
    rpcuser
    nfsnobody
    ntp
    qemu
    radvd
    sshd
    tcpdump
    oprofile
    avahi
    rtkit
    pulse
    avahi-autoipd
    mysql
  8. Ensure passwords expire by editing /etc/login.defs
    PASS_MAX_DAYS 360
    PASS_MIN_DAYS 14

    PASS_MIN_LENGTH 8
    PASS_WARN_AGE 32
    For any accounts that have already been created, run the following to enforce the new rules:

    chage -M 360 -m 14 -W 7 admin

References

Nov 15, 2012

Setting up a CentOS 6.3 Virtual Host

This guide outlines how I set-up my virtual host using CentOS 6.3 (a free release version of Red Hat Linux with all the branding removed). It's partially based on my previous installation guide. I also used my guide to create a bootable USB installation disk, but this guide should work equally well with the standard DVD install.

Installation

  1. Boot up your installation media (you may need to edit your BIOS to do so)
  2. Select 'Install or upgrade an existing system' from the menu
  3. Select your language and keyboard layout.
  4. Click next at the splash screen.
  5. Choose the 'Basic Storage Device' option
  6. Select the 'Fresh Installation' option
  7. Enter in the host-name of your new server (for best results you should append your domain name to the end so it works seamlessly with SSL certificates) i.e. testserver.example.com

    If you want to configure a static IP address click on the 'Configure Network' button, select the your network card (probably eth0) and enter away.

    If you are going to use DHCP, or just don't know, just hit 'Next'
  8. Select the correct timezone for you (just click a location on the map and it should select the closest one to you).
  9. Enter in an appropriate root password. Make as long and complex as possible (long sentences with mixed character types are easier to remember than jibberish strings; for instance 'My office is situated in 1234 fake street, Fakeville!')
  10. In this example we are going to go for a custom partition layout, so select 'Create Custom Layout'. If you are fine with defaults, just skip to part .
  11. Delete all existing partitions and do the following:
    • A /boot partition of about 100MB. Use the ext4 format

    • Create a LVM Physical Volume that fills up the rest of the hard-drive

    • Create a LVM Volume Group with a Physical Extent of 4MB.

    • Create LVM Logical Volumes on the Volume group as follows (make sure you leave some free space for your Virtual machines!!):

      • Swap space that is at least equal to how much RAM is in your server
      • /tmp/ should be as big as the largest file you will be manipulating (for instance, if you are copying a DVD you will need at least 4GB)
      •  /var/log and /var/log/audit are separated so that if your log system goes haywire it does not kill the space for other applications. Dedicate a couple of gigabytes to each.
      • /home/ and /usr/ should be a few gigabytes each. /usr/ just holds your applications and should remain pretty static, while /home/ is where you will store your personal files.
      • /var/ and /var/www/ will contain the majority of space on your system. MySQL stores your database files in /var/lib/mysql/, while Apache runs from /var/www/. Dedicate adequate space to each folder.
      • Your root folder (/) will only need a few GB of space. It will mainly hold configuration files.
  12. The system will take some time to format your hard-drive. Once it is complete it will ask you to install the boot-loader. While the defaults are suitable, for extra security you should consider password protecting your boot-loader.
  13. We can now select our packages. You can customize the system to suit your needs, but for the basics just select 'Basic Server' from the menu and the 'Customize now' from the radio buttons. Hit 'Next'.
  14. Do the following edits:
    • Remove the 'Java Platform' and 'Directory Client' meta-packages
    • Add all of the Virtualization meta-packages (including client, platform and tools)
    • Because the virt-manager tool requires a GUI, you may need to install the 'X Windows System'  and the 'KDE Desktop'
    • From the base system, I removed packages such as hunspell and word (as well as hardware tools like RAID that I was not using)
  15. Reboot your system!

 House cleaning

I suggest you take this time to tighten up your machine; run updates, turn off services, install software and harden your machine. You should also consider setting up your SSH settings.

Have a look at some of my guide to Software package integrity checks (aide).


Creating our first guest

We are going to use LVM based guests, so if you haven't left any space on your LVM partition I suggest you use these guides to free up some space. If you have partitions you don't think you need anymore, just delete it.

You may also want to ensure that KVM is installed so that you get the benefit from it's kernel and hardware virtualisation.

yum install kvm qemu-kvm qemu-kvm-tools

Now you just need to create a logical partition in the volume to store your VM by running the following command (assuming your volume is call VolGroup):

lvcreate -L20G -n vm1 VolGroup

To install to this new partition, just run the following command:

virt-install --connect qemu:///system -n vm1 -r 512 --vcpus=2 --disk path=/dev/VolGroup/lv_vm1 -c /path/to/installation.iso --graphics vnc --noautoconsole --os-type linux --os-variant rhel6

Note the following parameters:
  • -r specifies the RAM size
  • --vcpus specifies the virtual CPU's to use
  • --os-type helps to optimise the VM by specifying an operating system
  • --os-variant is a optional parameter, but helps further optimisation of the emulator.

Further reading

Nov 14, 2012

Installing CentOS 6.3 from a USB mass storage device

I've done A LOT of research on this issue and I have finally been able to create a bootable USB to use for installing CentOS.

  1. Download the Centos DVD for your system.

    (Optional: You can run the md5sum command on your download and compare the hash against that stored on the server)
  2. Clear the USB (NOTE: This is assuming your device is sdb!!! Double check, otherwise you may wipe your hard-drive!!!):

    sudo dd if=/dev/zero of=/dev/sdb bs=512 count=1
  3. Make it bootable (you can type in 'm' to show a help menu):

    sudo fdisk /dev/sdb
    >n
    >p
    >1
    >(default)
    >(default)
    >a
    >1
    >t
    >c
    >w
  4. Format the partition:

    sudo mkfs.vfat /dev/sdb1
  5. Download the livecd bash script and make it executable:

    wget http://git.fedorahosted.org/cgit/livecd/plain/tools/livecd-iso-to-disk.sh
    chmod +x livecd-iso-to-disk.sh
  6. Install the software required by the script:

    sudo apt-get install isomd5sum syslinux extlinux
  7. Run the script:

    sudo ./livecd-iso-to-disk.sh [your-dvd-iso] /dev/sdb1
  8.  Insert your USB device and run!

Further reading

 You can also see my other related articles:

Nov 12, 2012

Get page width dynamically with Javascript (or JQuery)

This quick script will display the current width of your browser window (useful for creating responsive web designs).

The HTML

Simply make a <div> element, which we will be used by JQuery to print out the window width:
<html>
  <body>
    <div id="dimensions">
      <span class="width"></span>
    </div>
  </body>
</html>

JQuery method

If you already use JQuery, then this is for you. If you aren't using it, you should consider it; it makes programming in Javascript a breeze!

To use this snippet, just download the JQuery library, link it into your page and add the following script:

<script>
  $("#dimensions .width").html($(window).width());
  $(window).resize(function(){
    $("#dimensions .width").html($(window).width());
  });

</script>

Javascript method

If you don't have JQuery this should work equally well:

<script>
  window.onresize = displayWindowSize;
  window.onload = displayWindowSize;
  function displayWindowSize() {
    // your size calculation code here
    document.getElementById("dimensions").innerHTML = myWidth + "x" + myHeight;
  };
</script>

Further reading

You can also browse my other content such as:

Oct 19, 2012

PERL script to connect and test PostgreSQL database

I decided to follow up my last getopts script about PERL scripting (which greatly improved upon my original PERL efforts) with a script that will attempt to connect to a PostgreSQL database and test if some tables exist or not.

I won't go into too much details and just paste the code here...

#!/usr/bin/perl -w
#
# This is a perl script that uses warnings (hence the -w flag)
#
# This perl scripts aims to test the database connections
# and ensure the schema conforms to the standard.

# Use strict perl
use strict;

# Use the Getopt library
use Getopt::Std;

# Creates a hash variable where we can store our command line options
my %options=();

# Grab the list of command line options (some with optional arguments,
#   denoted by a ':')
#   -u {username}   : Sets the username
#   -p {password}   : Sets the password
#   -H {hostname}   : Sets the hostname
#   -D {database}   : Sets the database
#   -h              : Displays the help
#   -d              : Debugging
getopts("hdu:p:H:D:", \%options);

# Sets some variables based on command line options, otherwise use defaults
my $username = (defined $options{u}) ? $options{u} : 'test';
my $password = (defined $options{p}) ? $options{p} : 'test';
my $hostname = (defined $options{H}) ? $options{H} : 'localhost';
my $database = (defined $options{D}) ? $options{D} : 'testdb';

# Set some environment variables
$ENV{PGPASSWORD}=$password;

# Output the display menu if asked for
if (defined $options{h}) {
    print "Test the database connections and ensure the schema conforms to the standard\n\n";
    print "usage: test.pl [-u <username] [-p <password>] [-H <hostname>]\n\n";
}

# Display the passed variables for debugging purposes
print "USERNAME: " .$username . "\nPASSWORD: " . $password . "\nHOSTNAME: " . $hostname . "\nDATABASE: " . $database . "\n\n" if defined $options{d};

# The auth tables
my @tables = qw(
system.session system.logs system.users);

# Loop through all our declared tables
foreach (@tables)
{
  psql_command($_);
}

# Clear some environmental variables
delete $ENV{PGPASSWORD};

# Exit from the system
exit 0;

# This subroutine runs a psql command
sub psql_command
{
  # Grab some parameters
  my ($table) = @_;
  if(!( defined($table)))
  {
    die "psql_command() was passed some bad arguments!\n";
  }

  my $output = `/usr/bin/psql -U $username -h $hostname -w -d $database -c 'SELECT * FROM $table' 2>&1`;
  if ( $? == -1 )
  {
    print "!!ERROR!! : $!\n";
  } else {
    if (($? >> 8) > 0)
    {
      print "!!ERROR!! : $table does not exist\n";
    } else {
      print "$table exists\n";
    }
  }

  return 0;
}

References:

Oct 18, 2012

PERL Script with command line options

It's been a long time since I have done a tutorial about PERL scripting, so I cracked my fingers and got down to hacking some code to create a basic command line script with options.

To give you an idea, I want to be able to run a command and pass some optional flags to it. For instance:

perl-script -h -username nassar

It turns out that this is a very simple thing to do because PERL has an inbuilt getopts function.

#!/usr/bin/perl -w
#
# This is a perl script that uses warnings (hence the -w flag)
#
# This perl scripts is a test of the getopts function

# Use strict perl
use strict;

# Use the Getopt library
use Getopt::Std;

# Creates a hash variable where we can store our command line options
my %options=();

# Grab the list of command line options (some with optional arguments,
#   denoted by a ':')
#   -u {username}   : Sets the username
#   -p {password}   : Sets the password
#   -H {hostname}   : Sets the hostname
#   -D {database}   : Sets the database
#   -h              : Displays the help
#   -d              : Debugging
getopts("hdu:p:H:D:", \%options);

# Sets some variables based on command line options, otherwise use defaults
my $username = (defined $options{u}) ? $options{u} : 'test';
my $password = (defined $options{p}) ? $options{p} : 'test';
my $hostname = (defined $options{H}) ? $options{H} : 'localhost';
my $database = (defined $options{D}) ? $options{D} : 'testdb';

# Output the display menu if asked for
if (defined $options{h}) {
    print "The '-h' flag was invoked\n\n";
}

# Output the display menu if asked for
if (defined $options{d}) {
    print "The '-d' flag was invoked\n\n";
}

print "USERNAME: " .$username . "\nPASSWORD: " . $password . "\nHOSTNAME: " . $hostname . "\nDATABASE: " . $database . "\n\n";

exit 0;

 Make sure the script is set to be executable and you will get output similar to the following:

nassar@computer:~$ ./test.pl -u test -d -h
The '-h' flag was invoked

The '-d' flag was invoked

USERNAME: test
PASSWORD: testslair
HOSTNAME: localhost
DATABASE: testslairdb

nassar@
computer:~$

References: