Archive for the 'Linux' Category

Expanding a LVM partition to fill remaining drive space

When I deploy new servers through VMWare ESX, I usually copy an existing base that I have already setup. I keep the base image VMDK size small so it is quick to copy. When I have copied the image and am setting up a new server, I adjust the size of the VMDK in VMWare and then use gparted to fill up the space that is added to the end of the virtual disk.

This works fine for normal partitions, but as I found out today, gparted doesn’t play so nicely with LVM. Anyway, to cut a long story short, these are the commands that I had to use to fill up the remaining space of the root partition. I could have created a new partition and then added this to the volume group, but I wanted to keep things clean. After all, LVM is supposed to make things easier.

Ill assume that you want to grow your root partition. Ill also assume that you have a basic LVM structure like the default CentOS 5 partitioning layout. Also, make sure you have a backup of the data on the partitions you will be messing with. When doing these kind of operations, it is very easy for data loss to happen. I did this and it worked for me but I can’t garuntee that it will for you. The main thing to watch out for is the partitioning layout I am using in this example.

/dev/sda1 = /boot
/dev/sda2 = VolGroup00
/dev/VolGroup00/LogVol00 = /
/dev/VolGroup00/LogVol01 = swap

First increase the size of your VMDK through the appropriate tool. I use VI Client to do this for ESX. Its a bit different for VMWare Workstation and VMWare Server. Then go through these commands:

[root@linux~]# fdisk /dev/sda

The number of cylinders for this disk is set to 5221.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:

1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
(e.g., DOS FDISK, OS/2 FDISK)

Command (m for help):

We now need to delete the sda2 partition and re-add it. When we re-add it, we can change the number of cylinders to fill the partition up with all the remaining space. Press p to print the current partitions.

Command (m for help): p

Disk /dev/sda: 42.9 GB, 42949672960 bytes
255 heads, 63 sectors/track, 5221 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          13      104391   83  Linux
/dev/sda2              14        5221    41833260   8e  Linux LVM

Command (m for help):

We want to delete partition 2 and re-add it again so we can fill up the remaining space. Press d and then select partition 2.

Command (m for help): d
Partition number (1-4): 2

Command (m for help):

Now we will re-create the partition. Set the partition number to 2, for the starting cylinder, set to whatever was the starting cylinder before. The default should be set as this anyway. For the end cylinder, leave the default as this will have the value of the last available cylinder.

Command (m for help): n
Command action
e   extended
p   primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (14-5221, default 14):
Using default value 14
Last cylinder or +size or +sizeM or +sizeK (14-5221, default 5221):
Using default value 5221

Command (m for help):

Finally we want to change the type to LVM (8E)

Command (m for help): t
Partition number (1-4): 2
Hex code (type L to list codes): 8e
Changed system type of partition 2 to 8e (Linux LVM)

Command (m for help):

Save and quit with w

Command (m for help): w

You will now need to reboot. After the reboot we use the pvresize command to fill out the extra space. As fair as I can tell, this resizes the amount of space that a LVM volume group can use on a partition and needs to be run if you resize its partition.

pvresize /dev/sda2

Now we need to resize the logical volume, LogVol00. We use lvresize for this. There is a funny looking argument that is passed to resize. We don’t say that we want to fill the rest of the volume, we say that we want to add 100% of the free space to the volume.

lvresize -l +100%FREE /dev/VolGroup00/LogVol00

Finally we want to resize the actual underlying file system. I am using ext3 for the root so I use the resize2fs command

resize2fs /dev/VolGroup00/LogVol00

There is no reboot needed after this. Do a df and see the results!

December 08 2009 | Linux | No Comments »

Provisioning a Linux web and shell server in an Active Directory environment

In this rather large tutorial, I will go over setting up a Linux server to be used for user web space, shell access, FTP access any anything else that is PAM aware. All user accounts will reside in Active Directory. There is no password syncronisation or dirty scripts to pull it all together.

Overview

This tutorial is based on the setup that I deployed recently at my work. We were wanting to give students web space but didn’t want to use IIS and also didn’t want to manually manage user accounts on a Linux server. I have used Samba/Winbind to join other web servers to our domain so that administrators can edit websites through SMB/CIFS instead of using FTP which had worked fine. This guide is basically an extension of that.

This guide will follow these steps listed below:

  • Step 1: Setup NTP to syncronise time
  • Step 2: Setup Kerberos
  • Step 3: Setup Samba
  • Step 4: Join the server to the domain
  • Step 5: Edit the nsswitch file
  • Step 6: Edit the fstab
  • Step 7: Add pam_winbind PAM module
  • Step 8: Edit the user skeleton directory
  • Step 9: Add the pam_mkhomedir module
  • Step 10: Setup Apache
  • Step 11: Setup vsftpd
  • Step 12: Optional: Setup quotas
  • Step 13: Optional: Setup IPTables
  • Step 14: Optional: Setup sudo

Quota’s, IPTables and sudo are optional steps but I reccomend that you at least read over why you might want them.

In the end you will have a server that does the following:

  • Users will be able to login using SSH with their Active Directory credentials
  • Users will be able to upload files to their website using FTP with their Active Directory credentials
  • Users will be able to upload files to their website through SMB/CIFS. If they are already logged onto the domain, they will not need to login again to access this.
  • Users’ home directories will be automatically created
  • Depending upon their AD group, users will have quotas automatically assigned.
  • Depending upon their AD group, users may or may not be able to access the Internet whilst using their shell
  • Depending upon their AD group, users will be able to sudo (useful for domain admins group to be able to sudo, as they don’t need to know the root password of the box)
  • And more! Anything that is PAM aware will be able to use AD credentials.

Step 0: Base CentOS 5 Install

This tutorial will be using CentOS. Why? Because it is stable, mature and pretty well supported. For servers, I run nothing else. We will also make a few assumptions regarding the setup:

  • Your domain is known as example.com
  • The short name/NT name of your domain is EXAMPLE
  • The host name for this server will be webs, with an IP of 10.0.0.50
  • Your have 2 domain controllers, with names dc1 and dc2. IP’s are 10.0.0.10 and 10.0.0.20
  • Your server has just one partition, the root partition. (This is only relevant for quota support)

Setup CentOS 5 on a server using as small a footprint as possible. You don’t need X or any of the development stuff. We will install the bits and pieces that you will need using yum along the way. I will assume that you have networking setup and your DNS servers are your DNS servers for your domain (usually your domain controller/s).

file: /etc/resolv.conf

search example.com
nameserver 10.0.0.10
nameserver 10.0.0.20

Also be sure to edit your hosts file and make sure this server name is listed in it.

file: /etc/hosts

127.0.0.1   localhost.localdomain localhost
::1         localhost6.localdomain localhost6
10.0.0.50   webs.example.com webs

Step 1: Setup NTP client

Install NTP using yum

# yum install ntp

Now ideally you would synchronise the time by editing the /etc/ntp.conf file and adding your domain controllers in as NTP servers. I have tried this a few times but I always end up with the clock out. It is very important to keep the clock in sync. If you have a clock skew of more than 5 minutes from your domain, you will loose authentication completely. I do something that isn’t ideal but it works. I set the ntpclient to syncronise the time every 5 minutes using cron. I have read that this is not recommended as the sudden change in time can upset things, but I have only read this and I haven’t come across any issues as of yet. If you choose to go down my route, add the following into your /etc/crontab.

file: /etc/crontab

*/5 * * * * root /usr/sbin/ntpdate -s dc1.example.com

Step 2: Setup Kerberos

Kerberos is an authentication scheme originally created at MIT. Windows 2000/2003/2008 domains use Kerberos and we need to set it up on the Linux server to be able to join it to AD. Edit your /etc/krb5.conf file to contain the following:

file: /etc/krb5.conf

[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = EXAMPLE.COM
 dns_lookup_realm = false
 dns_lookup_kdc = false

[realms]
 EXAMPLE.COM = {
  kdc = dc1.example.com:88
  kdc = dc2.example.com:88
  default_domain = example.com }

[domain_realm]
 .example.com = EXAMPLE.COM
 example.com = EXAMPLE.COM

[kdc]
 profile = /var/kerberos/krb5kdc/kdc.conf

[appdefaults]
 pam = {
   debug = false
   ticket_lifetime = 36000
   renew_lifetime = 36000
   forwardable = true
   krb4_convert = false
 }

If you only have one domain controller, don’t add in the line for the second one. That is it for Kerberos.

Step 3: Setup Samba

Samba is awesome. Winbind (part of samba) will be doing all the hard work to provide authentication details to SSH, FTP etc… from AD. Before we do anything though, we need to install it.

# yum install samba

It is a fairly large download, about 25MB. Once it has finished downloading and installing, move the example configuration file it comes with.

# mv /etc/samba/smb.conf /etc/samba/smb.conf.example

Now create /etc/samba/smb.conf and add the following contents, editing the parts that are suitable.

file: /etc/samba/smb.conf

[global]
# General name options
workgroup               = EXAMPLE
netbios name            = webs

server string           =

idmap uid               = 10000-20000
idmap gid               = 10000-20000

security                = ads
encrypt passwords       = yes

realm                   = example.com
password server         = dc1.example.com
os level                = 10
# Winbind Stuff - Active Directory
winbind enum users      = yes
winbind enum groups     = yes
winbind nested groups   = yes
winbind use default domain      = yes
template shell          = /bin/bash
template homedir        = /home/%D/%U
obey pam restrictions   = yes

# Disabled printing
load printers = no
printing = bsd
printcap name = /dev/null
disable spoolss = yes

# Extended ACL support
map acl inherit = yes
nt acl support = yes

[homes]
path                    = /home/%D/%U
browsable               = no
writable                = yes

[userhomes$]
path                    = /home/EXAMPLE
comment                 = User home directories
valid users             = @"EXAMPLE\Domain Admins"
writable                = yes
create mask             = 775
directory mask          = 775
admin users             = @"EXAMPLE\Domain Admins"

This file is pretty self explainatory. There is a bit of magic in the winbind section that sets the shell and  home directory for new users and also makes sure that Samba uses PAM (obey pam restrictions, which will be important later on). The [homes] share allows users to connect to their home directories which contains their web space. The second share is optional, [userhomes$]. This is a hidden share that is only available to domain admins that will allow them to browse all users home directories.

Finally we will want to start Samba and winbind and also make sure they start upon boot.

# /etc/init.d/smb start
# /etc/init.d/winbind start
# chkconfig smb on
# chkconfig winbind on

Step 4: Join server to the domain

This step will go over joining the server to the AD domain. Just like we would join a Windows XP machine, Server 2003, Server 2008 etc… member server to provide authentication services, so to do we join the server to provide the same services. The process is slightly more detailed but is still fairly easy.

First, we use kinit to get a Kerberos ticket and to test Kerberos is working

# kinit Administrator@EXAMPLE.COM
Password for Administrator@EXAMPLE.COM

Now do the join

# net ads join -U Administrator
Administrator's password
Joined 'WEBS' to realm 'EXAMPLE.COM'

Now test that we can get users and groups from AD.

# wbinfo -u
and
# wbinfo -g

If you can see users and groups of your domain, great! If not, you most likely got an error with the join. Double check some key areas such as your /etc/resolv.conf, hosts file and make sure that winbind is running. Also check your /var/log/samba/winbindd.log for any clues

Step 5: Edit the nsswitch.conf file

The nsswitch.conf file is the configuration file for the Name Service Switch. Basically it allows you to add and order the methods for looking up account information on the server. This is different from PAM. PAM gives us the authentication, but the Name Service Switch provides the server with account information typically found in a normal /etc/passwd file and /etc/group file. For example, if you want to chown a file to a domain user, nsswitch will lookup the databases configured, look in the local /etc/passwd file and then will use winbind to lookup that user on the domain if they don’t exist in the passwd file.

Edit the /etc/nsswitch.conf file so that winbind is added as a lookup method for passwd and group.

file: /etc/nsswitch.conf

passwd:     files winbind
shadow:     files
group:      files winbind

Leave the rest untouched.

Step 6: Edit the fstab

This is not really nesessary, but will allow you to set file permissions through Windows on files hosted on the server. We need to add the acl flag to the mount options of the file system where the user homes are. In this instance, there is only one partition, /. Remove the defaults option and replace it with rw,acl

file: /etc/fstab

LABEL=/                 /                       ext3    rw,acl        1 1

Now we need to remount the file system using the following command:

# mount -o remount /

This should take a few seconds. Now your file system is mounted with extended ACL support. Not only will it mean that samba can set permissions, but you will also be able to set more than the 3 default permissions (owner, group, others) on files and folders.

Step 7: Add winbind as a PAM module

This will give us the authentication to the server and will allow PAM aware programs (SSH, vsftpd) to know who we are and authenticate us. We need to add it to the auth, account and session parts of PAM. Open the /etc/pam.d/system-auth file and make the following changes:

file: /etc/pam.d/system-auth

#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        sufficient    pam_winbind.so
auth        required      pam_env.so
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        required      pam_deny.so

account     sufficient    pam_winbind.so
account     required      pam_unix.so
account     sufficient    pam_succeed_if.so uid < 500 quiet
account     required      pam_permit.so

password    requisite     pam_cracklib.so try_first_pass retry=3
password    sufficient    pam_unix.so md5 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

session     sufficient    pam_winbind.so
session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so

Take note of the warning up the top. authconfig will regenerate the file if it is run. Luckily, it seems the only way this is run is if you run it yourself. Upgrading CentOS versions (5.0 – 5.1 etc…) does not run authconfig again which I thought it might. Just remember what you did or write it down somewhere else incase it does get wiped.

Before you get ahead of yourself and try to login with SSH, we need to do a couple more things.

Step 8: Edit the user skeleton directory

The directory contained in /etc/skel is the directory where all new user accounts are sourced from. At the very least we need to add a folder to it so that all users will have a public_html directory. If you want to edit any other settings or add any default files or folders that all new user accounts will have, add them in here.

# mkdir /etc/skel/public_html

This will make sure that all new user accounts will have a public_html directory. This directory is the web root for the user.

Step 9: Add the pam_mkhomedir module

The pam_mkhomedir module will automatically create the user’s home directory if it does not already exist. This saves us having to write scripts that would get all the users out of AD and create their home directories for example. We add it to the system-auth file.

file: /etc/pam.d/system-auth

#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        sufficient    pam_winbind.so
auth        required      pam_env.so
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        required      pam_deny.so

account     sufficient    pam_winbind.so
account     required      pam_unix.so
account     sufficient    pam_succeed_if.so uid < 500 quiet
account     required      pam_permit.so

password    requisite     pam_cracklib.so try_first_pass retry=3
password    sufficient    pam_unix.so md5 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

session     required      pam_mkhomedir.so skel=/etc/skel umask=0022 silent
session     sufficient    pam_winbind.so
session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so

Add the section in bold to the file and save it. At this stage, AD users should be able to login using SSH and have their home directory automatically created for them. They should also be able to access their home directory through SMB/CIFS using a UNC path and if they are already logged into the domain they will not need to enter their credentials in again. Any other PAM aware applications that you also have installed on your server should also use AD to authenticate as well. In the next section, we will setup Apache to serve pages out of user home directories and also setup FTP for users to be able to access their home directories and upload files to their website.

Step 10: Setup Apache

We will now install and configure Apache to serve pages out of the users public_html directory. First, install Apache with yum and set it to start upon boot. Don’t start it yet though, we need to make a few changes to its config.

# yum install httpd
# chkconfig httpd on

Now open up /etc/httpd/conf/httpd.conf and scroll down to about line 350. Make the following changes in bold to the file and save it.

<IfModule mod_userdir.c>
    #
    # UserDir is disabled by default since it can confirm the presence
    # of a username on the system (depending on home directory
    # permissions).
    #
    # To enable requests to /~user/ to serve the user's public_html
    # directory, remove the "UserDir disable" line above, and uncomment
    # the following line instead:
    #
    UserDir public_html

</IfModule>

<Directory "/home/EXAMPLE/*/public_html">
        # Allow indexes
        Options +Indexes
</Directory>

This will enable user directories and also enable directory indexes for all users. Directory indexes will display a list of files and folders if there is no index.html, index.php etc… file. Some people choose not to enable this as it can be considered a bit of a security threat. This is true in some situations, but for the purpose of this server, I feel it makes it more functional having them turned on.

Now we will go ahead and start Apache.

# /etc/init.d/httpd start

Apache should start with no problems. Now go ahead and login as a domain user through SSH or SMB/CIFS and put something in their public_html directory. Apache serves user directories out of http://servername/~username. So in our setup, assuming we logged in as the user, user1, the URL would be http://webs/~user1. This would point to the root of user1’s public_html directory.

Step 11: Setup vsftpd

Vsftpd – Very Secure File Transfer Protocol Daemon, is the standard FTP server that ships with CentOS. Make sure it is installed via yum.

# yum install vsftpd

We need to edit the config file to change a few settings and to make sure that it uses PAM for its user database. Anything in bold you will need to change from the defaults.

file: /etc/vsftpd/vsftpd.conf

# Example config file /etc/vsftpd/vsftpd.conf
#
# The default compiled in settings are fairly paranoid. This sample file
# loosens things up a bit, to make the ftp daemon more usable.
# Please see vsftpd.conf.5 for all compiled in defaults.
#
# READ THIS: This example file is NOT an exhaustive list of vsftpd options.
# Please read the vsftpd.conf.5 manual page to get a full idea of vsftpd's
# capabilities.
#
# Allow anonymous FTP? (Beware - allowed by default if you comment this out).
anonymous_enable=NO
#
# Uncomment this to allow local users to log in.
local_enable=YES
#
# Uncomment this to enable any form of FTP write command.
write_enable=YES
#
# Default umask for local users is 077. You may wish to change this to 022,
# if your users expect that (022 is used by most other ftpd's)
local_umask=022
#
# Uncomment this to allow the anonymous FTP user to upload files. This only
# has an effect if the above global write enable is activated. Also, you will
# obviously need to create a directory writable by the FTP user.
#anon_upload_enable=YES
#
# Uncomment this if you want the anonymous FTP user to be able to create
# new directories.
#anon_mkdir_write_enable=YES
#
# Activate directory messages - messages given to remote users when they
# go into a certain directory.
dirmessage_enable=YES
#
# Activate logging of uploads/downloads.
xferlog_enable=YES
#
# Make sure PORT transfer connections originate from port 20 (ftp-data).
#connect_from_port_20=YES
#
# If you want, you can arrange for uploaded anonymous files to be owned by
# a different user. Note! Using "root" for uploaded files is not
# recommended!
#chown_uploads=YES
#chown_username=whoever
#
# You may override where the log file goes if you like. The default is shown
# below.
#xferlog_file=/var/log/vsftpd.log
#
# If you want, you can have your log file in standard ftpd xferlog format
xferlog_std_format=YES
#
# You may change the default value for timing out an idle session.
#idle_session_timeout=600
#
# You may change the default value for timing out a data connection.
#data_connection_timeout=120
#
# It is recommended that you define on your system a unique user which the
# ftp server can use as a totally isolated and unprivileged user.
#nopriv_user=ftp
#
# Enable this and the server will recognise asynchronous ABOR requests. Not
# recommended for security (the code is non-trivial). Not enabling it,
# however, may confuse older FTP clients.
#async_abor_enable=YES
#
# By default the server will pretend to allow ASCII mode but in fact ignore
# the request. Turn on the below options to have the server actually do ASCII
# mangling on files when in ASCII mode.
# Beware that on some FTP servers, ASCII support allows a denial of service
# attack (DoS) via the command "SIZE /big/file" in ASCII mode. vsftpd
# predicted this attack and has always been safe, reporting the size of the
# raw file.
# ASCII mangling is a horrible feature of the protocol.
#ascii_upload_enable=YES
#ascii_download_enable=YES
#
# You may fully customise the login banner string:
ftpd_banner=Welcome to example.com WEBS FTP server!
#
# You may specify a file of disallowed anonymous e-mail addresses. Apparently
# useful for combatting certain DoS attacks.
#deny_email_enable=YES
# (default follows)
#banned_email_file=/etc/vsftpd/banned_emails
#
# You may specify an explicit list of local users to chroot() to their home
# directory. If chroot_local_user is YES, then this list becomes a list of
# users to NOT chroot().
#chroot_list_enable=YES
# (default follows)
#chroot_list_file=/etc/vsftpd/chroot_list
#
# You may activate the "-R" option to the builtin ls. This is disabled by
# default to avoid remote users being able to cause excessive I/O on large
# sites. However, some broken FTP clients such as "ncftp" and "mirror" assume
# the presence of the "-R" option, so there is a strong case for enabling it.
#ls_recurse_enable=YES
#
# When "listen" directive is enabled, vsftpd runs in standalone mode and
# listens on IPv4 sockets. This directive cannot be used in conjunction
# with the listen_ipv6 directive.
listen=YES
#
# This directive enables listening on IPv6 sockets. To listen on IPv4 and IPv6
# sockets, you must run two copies of vsftpd whith two configuration files.
# Make sure, that one of the listen options is commented !!
#listen_ipv6=YES

pam_service_name=vsftpd
userlist_enable=YES
tcp_wrappers=YES
chroot_local_user=YES
session_support=YES

Save and close the file. An important line in the file is session_support=YES. This is not talking about an FTP session, but rather to make sure to use PAM session support. This means that it will run the pam_mkhomedir module and any other session modules that we configure. Now start proftpd and also don’t forget to add it to start on boot.

# /etc/init.d/vsftpd start
# chkconfig vsftpd on

Thats it! You can stop now and you will have a fully functional shell/web server for users of your Active Directory. If you continue I will go over setting up quotas, securing access using IPTables and allowing the Domain Admins group root access.

Step12: Optional – Setup quotas

Quotas will limit the amount that users are allowed to store on the server. This prevents users using their webspace to host large files which is probably what we want as administrators. The quotas can be based on a group so that in this case, anyone who is a member of the group “students” will be alloted 100MB. Note that this support of quotas based on groups is not Linux “group quotas” which will allot a group of users an overall quota. Also note that this support of quotas based on groups is not natively supported, but will can be by using a script that is executing upon login using PAM.

But before we go into details, we need to setup quota support on the file system. This guide assumes that you have just one partition, your root partition. If you have your /home on another partition, then set the quota options to your /home partition. We will edit the /etc/fstab file to enable the support and then remount the file system.

file: /etc/fstab

LABEL=/                 /                       ext3    rw,acl,usrquota 1 1
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
LABEL=SWAP-sda2         swap                    swap    defaults        0 0

# mount -o remount /

Add the usrquota option to enable user quotas. Now we need to create the file that will store the user quotas.

# touch /aquota.user
# chmod 600 /aquota.user
# chown root:root /aquota.user

Now we run quotacheck to get the most recent state of our quotas.

quotacheck -vgum /

Quota support is now enabled. Now there are a few ways to apply quotas to users. We can use the command line programs to manually apply quotas to users (very undesirable), write a script that fetches all the users in AD and applies a quota to each user every hour or so (also undesirable), use the pam_setquota module, or use the pam_script module and run a script at the PAM session stage. I couldn’t get the pam_setquota module to compile (latest source I could get was 2006), so I used the pam_script module and wrote a script that would run whenever a user logged in, used samba or used FTP. Create the following script in /usr/local/bin/quota_set.sh.

file: /usr/local/bin/quota_set.sh

#!/bin/bash
# Sets the users quota to 100MB if they are a student
#
# Get the user name
user=$1

# Will return a string if the user is a student
retval=`groups $user`

# If the user is a student, then set the quota to 100MB
if [[ $retval =~ " student " ]]
then
  # Set the quota of the user to 100MB, with a 120MB hard limit
  setquota -u $user 100000 120000 0 0 -a /
fi

Read through the comments to see how it works. Change the bolded value to match the group of your users. In this instance, all students are members of the AD group “student”. Note that anyone with the string ” student ” (note the spaces between student) will have this quota applied to them. Also feel free to change the amount of quota users get (the 100000 and 120000 values, where 1 = 1kB).

Also don’t forget to make it executable.

# chmod +x /usr/local/bin/quota_set.sh

Now we need to add this as a parameter of the pam_script module. First lets make sure that pam_script is installed.

# yum install pam_script

Now edit the /etc/pam.d/system-auth file to include this module

file: /etc/pam.d/system-auth

#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        sufficient    pam_winbind.so
auth        required      pam_env.so
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        required      pam_deny.so

account     sufficient    pam_winbind.so
account     required      pam_unix.so
account     sufficient    pam_succeed_if.so uid < 500 quiet
account     required      pam_permit.so

password    requisite     pam_cracklib.so try_first_pass retry=3
password    sufficient    pam_unix.so md5 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

session     required      pam_mkhomedir.so skel=/etc/skel umask=0022 silent
session     required      pam_script.so runas=root onsessionopen=/usr/local/bin/quota_set.sh
session     sufficient    pam_winbind.so
session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so

When a user opens a session (using FTP, logging into SSH etc…) this script will be run and will set the user’s quota. Note that the quota can be changed later down the track as the script will run everytime a PAM session is created.

Step 13: Optional – Setup IPTables

This step will be dependant on the hostility of the users. This server was originally comissioned for use in a school environment. The possibility for users to use this server as a tunnel out to the Internet was not just a possibility, but a ceartainty. But what about PHP proxy scripts you might ask? Well that can be solved as well. We will use IPTables user matching module to allow outgoing connetions to only ceartain user groups. The idea of matching users based on their group might sounnd really cool, and that’s because it is.

CentOS luckily has this support already enabled. Below is the firewall script that I use and it works quite well. Create a file /etc/sysconfig/firewall.sh and add the following:

file: /etc/sysconfig/firewall.sh

#!/bin/bash
# Flush tables
iptables -F

# Set defaults
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

########## INPUT RULES ##########
# Stateful inpection input
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow HTTP
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# Allow SSH from internal network
iptables -A INPUT -s 192.168.0.0/24 -p tcp --dport 22 -j ACCEPT
# Allow FTP
iptables -A INPUT -p tcp --dport 21 -j ACCEPT
# Allow ping
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

######### OUTPUT RULES ##########
# Set some default outgoing rules that are allowed
iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT

# Only allow domain admins and root to make new outgoing connetions that
# are not pre-defined
#
# Need to do this so students don't use this server to tunnel to the
# internet, access web, ssh to different servers etc...
#
# Accepted users
#
iptables -A OUTPUT -m owner --gid-owner domain\ admins -j ACCEPT
iptables -A OUTPUT -m owner --gid-owner root -j ACCEPT
iptables -A OUTPUT -p tcp --sport 80 -m owner --uid-owner apache -j ACCEPT
#
# Rejected users
#
iptables -A OUTPUT -m owner --gid-owner domain\ users -j REJECT
iptables -A OUTPUT -m owner --gid-owner apache -j REJECT

# Finally accept new connections if no other match is made
iptables -A OUTPUT -m state --state NEW -j ACCEPT

The important lines are at the end of the file bolded. By default, we want to make sure that the AD group “Domain Admins” is allowed to make new connections as well as the “root” group. Also, the rule matching the Apache user with a source port of 80 is important as we want to make sure Apache is allowed to send out packets from its sessions but we want to restrict it from sending out new connections which would be the Apache user attempting to access a web site to proxy to the user. We then need to REJECT users that haven’t matched already. The AD group “Domain Users” will be denied access as well as Apache from making outgoing connections.

Now we want to make the file executable and add it to the /etc/rc.local. There is a “correct” way to do firewalling/IPTables in CentOS but I prefer to write a firewall script and run it on boot.

# chmod 700 /etc/sysconfig/firewall.sh
# chown root:root /etc/sysconfig/firewall.sh
# echo "/etc/sysconfig/firewall.sh" >> /etc/rc.local

Apply the firewall and make sure everything still works

# /etc/sysconfig/firewall.sh

NOTE: You might notice that all users are allowed to ping. This is because an ICMP ping packet is generated in the kernel space and not in userland programs, therefore the owner of the packet is root and not the user. Try using links or wget to confirm that the user matching works as these packets will be owned by the user that is requesting them.

Step 14: Optional – Setup sudo

Sudo, or super user do, allows you run or do things as root using your normal user account. You don’t need to know the root password, but just have to be in the /etc/sudoers file. You can allow users to do everything, or just a select few things. What we want to do is allow Domain Admins full access to the server, like they have full access to other member servers (by default).

We can’t edit the sudoers file directly, but rather have to edit it using the visudo command. Add these lines after you have run visudo

# visudo

file: /etc/sudoers

## Allows domain admins root privilages using their password
%Domain\ Admins	ALL=(ALL)	ALL

Now Domain Admins will have root prviliges using their current credentials.

Conclusion

You should now have a web/shell/FTP server that will authenticate off Active Directory. If you chose to add in the extra steps, your server will be even more secure against possible misuse. There are more things that you can do such as emailing users who have gone over their quota and searching for and deleting media files (mp3, avi, etc…). I’ll leave these things up to you if you wish to implement them.

Feel free to comment with suggestions, questions or to correct any mistakes.

August 31 2009 | Linux and Windows | 4 Comments »

Recieving some *smart* spam

Recently I have witnessed and received some spam that appears to be more resiliant to some filtering techniques. I have noticed this from work as well as mail that I host from home. The email headers look a lot nicer and seem less random.

Spam filtering at work uses a combination on Postfix header checks, RBL’s, SpamAssassin, SFP checks and greylisting. At home I use the same combination except I currently omit greylisting.

Ill give you an example of the spam message I revieved

Salve,

F**k beer! Got sexy girl?
Click here

Andyou meanthe police will have to be involved? Comprehend?
that which i see, i seei long have for sixteen hours we
halted at eight o’clock a.m. But as soon as they entered
such places, the diamond statues which represent buddha
in his lotus, or eyes on him again. I do hope he wasn’t
hurt. Lavinia he said. Things are much worse for jim pearson
next to it is the very handsome fruit garden of rack, or
loin, of mutton, otherways, whole, or seems my weeks of
training these dropout, unemployed, and it hurt dr. Conwell
so much that for ten years and get along. The thing for
you to do is to go me to clear out for a bit till she came
to her bad nervous breakdown. Finally, they said she and
shaves at least once a day. Like most men

This looks like a pretty typical spam email so far. The part that I find interesting is in the headers. I’ll only show the parts that are important.

Received: from oexrk.telecomitalia.it (hostxxx-68-static.89-82-b.business.telecomitalia.it [82.89.68.xxx])

The part that I find interesting is that the SMTP helo was from oexrk.telecomitalia.it and the reverse DNS is host198-68-static.89-82-b.business.telecomitalia.it. It looks like the spam bot is aware of the reverse DNS of the client computer that it has infected and making sure that it appears in the helo. The hostname part of the helo (oexrk) looks to be random characters that are then appended to the domain name. This could potantially trick some spam filtering software into a lower score as the helo is related to the reverse DNS. As well, the spam bot is also aware of greylisting and waits the appropriate length of time. This can be seen on the headers of the spam filtering at my work.

X-Greylist: delayed 306 seconds by postgrey-1.27 at mail.mywork.example.com; Fri, 11 Jul 2008 04:51:35 EST

We recieved several more spams from various other ISP’s that seem to all be infected with the same bot. Below are some more examples of the helo’s that were sent. They all follow a simmilar pattern of 2 levels of the domain name with 4-6 random characters appended as the hostname.

Received: from uezvl.inetia.pl (77-253-25-xxx.adsl.inetia.pl [77.253.25.xxx)
Received: from mmdodz.telecomitalia.it (hostxxx-123-static.23-87-b.business.telecomitalia.it [87.23.123.xxx])
Received: from peiwjh.telecomitalia.it (hostxxx-171-dynamic.16-87-r.retail.telecomitalia.it [87.16.171.xxx])
Received: from edny.telecomitalia.it (hostxxx-155-dynamic.40-79-r.retail.telecomitalia.it [79.40.155.xxx])

July 17 2008 | Linux | 1 Comment »

Active HTTP virus filtering with Squid and ClamAV using HAVP

***UPDATE 11.05.2008***: You will occasionally get errors about temporary directories that are failing to be created properly. To be honest, I don’t know what the cause of this is. It seems that either my setup (more likely) or HAVP is not production ready. If you force reload the page (ctrl + F5) the page should load properly afterwards. Also, after I wrote this tutorial, I realised that there was a HAVP RPM in the Dag repository. If you want to tweak this setup to use the Dag RPM, go ahead. Configuration file locations may vary though, so I cannot guarantee that these instructions will be completely portable.

I have had some trouble with finding a suitable solution for virus scanning using Squid. I tried squidclam which I didn’t have too much success running. There was also a plug-in for DansGuardian that provided virus filtering but I didn’t want the overhead of Dans and only wanted the virus scanning. Most of this guide is taken directly from http://www.opensourcehowto.org/how-to/squid/squid-clamav–havp.html with a few adjustments that were needed for my setup.

This setup assumes that you using CentOS 5 and already have Squid running and installed. If you need to setup Squid, Google is going to be your friend. There are heaps of tutorials around dealing with this. Also, if you run any redirect scripts such as Adzapper, this is fine as we will not be using this functionality of Squid to plug-in, but setting up a cache peer. More on that later.

INSTALLING CLAMAV

If you have not got Dag Wieers repo you will need to add this to the /etc/yum.repos.d/ directory to install ClamAV. Create a file in the yum.repos.d directory, /etc/yum.repos.d/Dag.repo and add the following:

[dag]
name=Dag RPM Repository for Red Hat Enterprise Linux
baseurl=http://apt.sw.be/redhat/el$releasever/en/$basearch/dag/
gpgcheck=1
gpgkey=http://dag.wieers.com/packages/RPM-GPG-KEY.dag.txt
enabled=1

We will need the development tools to compile HAVP. Install these and ClamAV with the following commands.

yum groupinstall "Development Tools"
yum install clamav clamav-devel

This will take some time. You could probably install the tools that you will need to compile HAVP by hand, but the Development Tools meta-package will alleviate some headaches later on. An updater script will be placed in /etc/cron.daily/freshclam. Modify the frequency of this to your own needs.

Now we will download HAVP and compile it. Head over to http://www.server-side.de/download.htm to get the latest version. 0.87 was the most current at the time of writing.

cd /tmp
wget http://www.server-side.de/download/havp-0.87.tar.gz
tar zxvf havp-0.87.tar.gz
cd havp-0.87
./configure
make
make install

SETTING UP FOR HAVP

This will install most of the files in /usr/local. Before we start messing around with the config file, we need to create a new user account for HAVP to run under and create a few directories/change some permissions.

First we will add the havp user

adduser -c "HAVP proxy virus scanner" -M -s /bin/false havp

Now we need to change the permissions of some directories that HAVP uses

chown -R havp:havp /var/run/havp
chown -R havp:havp /var/log/havp

HAVP requires a directory to store its temporary files. This file system MUST have mandatory locking enabled to function. We can cheat a bit to get around this by creating an image file and then mounting the image on the file-system with locking enabled. For this we will use the command dd.

dd if=/dev/zero of=havp.img count=1 bs=256M

This will create the image, havp.img with a size of 256 MB. Change the size to suit but I feel 256 MB is about enough. Move the image to an appropriate directory, format it and then mount it. This shown below.

mv havp.img /usr/
mke2fs /usr/havp.img
(You will get some errors about doing this operation, Just accept them).
mount -o loop,mand /usr/havp.img /usr/tmp/havp
chown -R havp:havp /usr/tmp/havp

We will also want this to mount at boot time so add the following to your /etc/rc.local. I originally added a line in my fstab, but realised this didn’t work when my machine failed to boot properly next time i rebooted it.

mount -o loop,mand /usr/havp.img /var/tmp/havp

CONFIGURE HAVP

Now its time to configure HAVP. Open /usr/local/etc/havp/havp.config in your favorite editor. Everything is commented out. There are a lot of defaults set, but we will take away a lot of the commented out lines just so we know exactly what is going on. Below are all the changes you will want to make.

#REMOVETHISLINE deleteme
USER havp
GROUP havp
DAEMON true
PIDFILE /var/run/havp/havp.pid
SERVERNUMBER 20
MAXSERVERS 100
ACCESSLOG /var/log/havp/access.log
ERRORLOG /var/log/havp/havp.log
LOG_OKS false
LOGLEVEL 0
SCANTEMPFILE /var/tmp/havp/havp-XXXXXX
TEMPDIR /var/tmp
PORT 8080
BIND_ADDRESS 127.0.0.1
SCANIMAGES false
(leave this enabled if you have a fast machine)
MAXSCANSIZE 5000000
KEEPBACKBUFFER 200000
ENABLECLAMLIB true

You will only really want to change settings relating to the scan size, buffers and streaming options. Also enable image scanning if you have the grunt.

Save and start HAVP using the init script that it installed

/etc/init.d/havp start

The HAVP init script does not work with chkconfig, so we can just tell it to start upon system boot by entering it in the /etc/rc.local file.

echo "/etc/init.d/havp start" >> /etc/rc.local

Check the logs to make sure that it has started properly. The logs a pretty useful and do give you a good indication to the cause of a problem if you have one. It will most likely be problems with permissions so checking these will be a good start.

CONFIGURE SQUID

Lastly we need to add HAVP as a cache peer of Squid, Open the /etc/squid/squid.conf file and enter the following line.

cache_peer 127.0.0.1 parent 8080 0 no-query no-digest no-netdb-exchange default

TESTING

Now restart Squid. Once Squid as restarted and all calmed down (the AdZapper script initially seems to add quite a delay to Squid responding once it has started), check you can initially access the web. If this is fine, we can now test our virus scanning. A special test signature called “eicar” has been created for the purpose of testing anti-virus programs. Head over to http://www.eicar.org/anti_virus_test_file.htm and try to download one of the files (through HTTP). If all goes well, you should receive a message such as shown below.

If you have got to this point, congratulations. If you are still having trouble, check the Squid logs as well as the HAVP logs. You might want to change the verbosity of the HAVP logs to check exactly what is happening. Remember, this is definitely not bulletproof. Both the fact that ClamAV is not the best engine for detecting viruses as well as the fact that only a certain file size will be scanned.

April 11 2008 | Linux and Uncategorized | 2 Comments »

Extended ACLs with Samba 3 in a 2K3 environment

There are a few documents around dealing with extended ACL support in Linux and Samba, but little documentation about its current implementation. The solution I came up with allows for domain admins to have the same level of control on files and directories as the root user and set permissions as one would on a 2003 server with NTFS permissions.

First, I am going to assume that you have Samba authenticating off a Windows 2000/2003 domain using Winbind. If you haven’t set this up, there are numerous documents around that deal with this. I will write another post at a later date on how to do this when I get the time. Also, I will assume that you are using the latest Samba RPM as it should contain support for extended ACLs. The third assumption is that you are using ext3 and that ACL support is enabled in the kernel. CentOS 5 has all of this enabled, so I will be using this as a base.

First, lets enable ACL support on our file system that will host out Samba shares. Open up /etc/fstab and change the line below

/dev/sda1 / ext3 defaults 1 1

to:

/dev/sda1 / ext3 rw,acl 1 1

Now we need to remount the root file system by issuing the following command

mount -v -o remount /

This may take a few minutes. It took about 3-4 for myself. Once this is complete, we will edit our smb.conf file to include the following [global] configuration options

[global]
....
map acl inherit = yes
nt acl support = yes
....

This allow extended ACLs to be applied to the file system. Now we need to allow domain admins permission to change ACLs on the files contained within the shares. Because Linux/UNIX only allows the owner or root to change the permissions of a file, we use the “admin users” option on the share to overwrite this. Edit the smb.conf file to include the following on the selected share.

[sharename]
path = /home/share
....
admin users = @"DOMAIN\Domain Admins"

Restart samba and now try accessing the share from a Windows machine. Check the security tab and add a user in just for kicks. Apply and close the properties window. Now open it again to make sure that the security was retained. If everything was setup correctly, the user you added permission to should still be there. It should look something like below.

extended acls 1

We can also check our Samba server file system permissions using the getfacl tool. This is what it look like if we execute it on the share that we set the permissions on before.
extended acls 2

Here we can see that there are both the normal UNIX permissions (displayed up the top of the window, on each line starting with #) and the extended permissions.

Conclusion
Extended ACLs aleviate a lot of permissions headaches when working with Samba in a Windows domain environment. It saves having to continuously chown files that get re-owned by root when you do ceartain functions on them. Also, some files are required to be owned by root (such as VMware virtual machine configuration files), and adding extended ACLs means that we can still copy and manage these VM files without having to chown them to move the files and then chown them back one they are copied accross.

Referrences
http://c.mills.ctru.auckland.ac.nz/Samba/XfsAclWinAuth.html
http://articles.techrepublic.com.com/5100-10878_11-6091748.html

December 20 2007 | Linux and Windows | No Comments »

Webmin for CentOS 5

I was supprised to find that there was no RPM provided by yum for webmin; neither in the base packages or Dag repository. For anyone who wants it is is avalible using my yum repository. Add the following to a file /etc/yum.repos.d/Doylenet.repo

[doylenet]
name=Doylenet custom repository for CentOS
baseurl=http://files.doylenet.net/linux/yum/centos/5/i386/doylenet/
gpgcheck=1
gpgkey=http://files.doylenet.net/linux/yum/centos/RPM-GPG-KEY-rdoyle
enabled=1

You can now install it using the command below

yum install webmin

Accessing Webmin is as easy as going to https://server:10000 and logging in with your root account.

October 28 2007 | Linux | 16 Comments »

PPTP using Poptop on CentOS 5

Just recently I needed to setup a quick and dirty VPN solution. I’ve used Poptop before on Mandrake 9 many years ago and it proved to be pretty easy to setup. Its even easier with CentOS 5, as the kernel is already patched with MPPE and MPPC encryption and authentication that is really required to create a secure VPN solution.

INSTALL AND CONFIGURE POPTOP

Firstly, make sure that ppp is installed using yum.

yum install ppp

I compiled the latest pptp version so grab the RPM from here and install it or add my custom yum repository. I would reccomend the latter as yum will update PPTP if I put an updated PPTP package on my yum repo.

If you would prefer to use my yum repository which also has a few other updated packages such as the patched iptables for L7 filtering (which I will talk about in a later post), you can add it by creating a new file “/etc/yum.repos.d/Doylenet.repo” and adding the following lines

[doylenet]
name=Doylenet custom repository for CentOS
baseurl=http://files.doylenet.net/linux/yum/centos/5/i386/doylenet/
gpgcheck=1
gpgkey=http://files.doylenet.net/linux/yum/centos/RPM-GPG-KEY-rdoyle
enabled=1

Once you have created this file, we need to install pptpd through yum.

yum install pptpd

Now we want to edit the /etc/pptp.conf file. Disable the line “logwtmp” by commenting it out otherwise PPTP will fail to start and get this error in the syslog, “Plugin /usr/lib/pptpd/pptpd-logwtmp.so is for pppd version 2.4.3, this is 2.4.4″. Like the error says, the library file is for PPP 2.4.3, but CentOS 5 uses 2.4.4. EDIT: This has now been corrected in the RPM package as pointed out by Peter. It is no longer required to disable this line.

Scroll down to the area localip and remoteip. So that we can keep routing issues to a minimum, set this to a range in your local LAN. For example, I use 10.0.0.0/24 for my private LAN. 10.0.0.1 is the IP address of my router and VPN server. I set the localip value to 10.0.0.2 and the remoteip range to 10.0.0.200-220, outside the DHCP assigned range.

localip 10.0.0.2
remoteip 10.0.0.200-220

Now edit the /etc/ppp/options.pptpd file. The defaults in here are fine as they are secure by default. The VPN will not form unless MSCHAPv2 is being used for authentication and 128bit MPPE encryption. Scroll down to “ms-dns”. It is commented out by default. Edit this to your internal DNS server address. Do this for WINS as well. If you don’t have an internal DNS server, this is fine, but name resolution is a lot less painful if you are using DNS and not relying on NetBIOS which requires broadcasts and doesn’t really work to well over a VPN.

# If pppd is acting as a server for Microsoft Windows clients, this
# option allows pppd to supply one or two DNS (Domain Name Server)
# addresses to the clients. The first instance of this option
# specifies the primary DNS address; the second instance (if given)
# specifies the secondary DNS address.
ms-dns 10.0.0.240
#ms-dns 10.0.0.2# If pppd is acting as a server for Microsoft Windows or "Samba"
# clients, this option allows pppd to supply one or two WINS (Windows
# Internet Name Services) server addresses to the clients. The first
# instance of this option specifies the primary WINS address; the
# second instance (if given) specifies the secondary WINS address.
ms-wins 10.0.0.240

Finally we want to edit the file /etc/ppp/chap-secrets. This is where we will specify user names and passwords. Each user is specified on a new line.

username * password *

This is all the configuration that is needed as far as the PPTP server goes. Start it using the following command.

/etc/init.d/pptpd start

FIREWALL AND ROUTING

The only issues now that need to be resolved are routing and firewall issues. This is only relevant if the VPN server is on the same server as your firewall/router. By having the VPN clients on the same subnet as the rest of the trusted LAN, it makes it easier for the client, but slightly harder to configure, as we aren’t dealing with Layer 3. We need to allow the interface ppp0 access to the trusted interface. We will assume eth0 is the trusted interface

iptables -A INPUT -i ppp0 -j ACCEPT
iptables -A FORWARD-i ppp0 -o eth0 -j ACCEPT

This could also be done using the 10.0.0.0/24 range, but this will only work for unicast addresses. To make these statements safe, 10.0.0.0 should be dropped at the external interface as well if not already done so. Its good practice to drop all RFC 1918 private addresses that which have their source address incoming from the external interface. A lot of malformed and spoofed IP packets often have source addresses from the private address range.

iptables -A INPUT -i eth0 -s 10.0.0.0/24 -j ACCEPT
iptables -A FORWARD -i eth0 -s 10.0.0.0/24 -j ACCEPT

Now we need to allow the VPN protocols that will be used to connect and communicate with the VPN server through our firewall. The authentication part of our VPN server uses the PPTP protocol which is on TCP port 1723. Actual data is then transfered using IP protocol GRE (Genertic Routing Encapsulation). Configure the following iptables commands.

iptables -A INPUT -i $external_interface -p tcp --dport 1723 -j ACCEPT
iptables -A INPUT -i $external_interface -p gre -j ACCEPT

CONNECTING A WINDOWS CLIENT

Lastly, we will want to setup the client. Windows 2000 and XP and (i assume) Vista, come with a PPTP VPN client that is installed by default. You can get to it by going to the “Network Connections” dialog and clicking “Create a new connection”. Follow the wizard through selecting Connect to the network at my workplace > Virtual Private Network connection > Enter in a name for the connection > Enter in the IP or preferably DNS name of the VPN server. If the VPN server is the router/gateway, you can use your external IP address in your LAN. For testing purposes, I used the internal address of 10.0.0.1. If you run an internal DNS, use that name so when you are away from home you VPN in, it will grab the external address as long as you have set everything up properly (in terms of external DNS). For this, I reccomend you use the services provided at DynDNS or a simmilar free DNS provider.

vpn1.JPG

Click “Properties”.

vpn2.JPG

Navigate to the screen above and click “Properties” again.

vpn3.JPG

Then “Advanced”

vpn4.JPG

Then untick “Use default gateway on remote network”. This statement is important and needs to be unticked most of the time for simple VPN setups. What this means is that you existing default gateway will be used (what ever you are connecting through the internet to) for all traffic that isn’t related to the VPN. Remember how we used the same subnet for the VPN clients as the LAN clients? This is because if we used another subnet, the VPN clients would not know how to get to the LAN. This would require the Use default gateway on remote network to be ticked, but would also mean all unrelated traffic would go through the VPN. The technical term for this is “Split Tunneling” and can be a security concearn with larger enterprises as there is a potential for the remote user to be a gateway into the corporate network. Our setup is rather simple and we trust the users that are connecting, so this is not a concearn.

Once you have this option set, use the username and password that was set in the chap-secrets file to connect and to test your VPN.

October 01 2007 | Linux | 72 Comments »

LDAP Authentication with Apache2 using Acitve Directory

LDAP authentication in Apache allows user and group authentiction from Active Directory to provide secutiry for files and folders using the users domain credentials. The only downfall of using LDAP authentication is that it isn’t SSO (Single Sign On). The user name and password used to authenticate is the same, but the browser doesn’t pass this info on like NTLM does. Anyhow, it is a useful authentication method regardless, as NTLM lacks proper group support in Apache.

Like everything else, this will be built using CentOS5. Install it in a minimal install. I will go through the packages that need to be installed next. Once CentOS is installed and up and running, login and we will install Apache. The default httpd package includes LDAP suppor, so we don’t need to install any other modules for it. There is a module called mod_authz_ldap. When I was originally setting this up, I thought that this was required, but didn’t realise that Apache supported LDAP out of the box.

Before we install Apache, we may as well update the all packages of the system.

yum update

This will take a while to complete and may download a few hundred MB of updates depending on what you installed. When this is complete, we will install Apache2

yum install httpd

This should only be a little over a MB. Once this is installed, we will create a directory that we want secured. For simplicity sake, we will just create it in the default web root. It can be applied for vhosts etc… as well.

mkdir /var/www/htlm/secure

Just to test it, we will make a simple web page in this folder

echo “<htlm><h1>It works!</h1></html>” > /var/www/htlm/secur/index.html

Now we will edit the /etc/httpd/conf/httpd.conf file to apply security to the “secure” directory. This can also be achieved using a htaccess file, but I really DON’T like htaccess files. They are harder to organise than applying security settings directly to vhost files of the httpd.conf file. Open the httpd.conf file in Vim

vim /etc/httpd/conf/httpd.conf

Go right to the end of the config (just hold page down) . Oncethere we want to enter the following.

<Directory “/var/www/htlm/secure”>
AuthType Basic
AuthName “LDAP Authentication”
AuthBasicProvider ldap
AuthLDAPURL ldap://dc.example.com:389/OU=USEROU,DC=example,DC=com?sAMAccountName?sub?(objectClass=user)
AuthLDAPBindDN cn=binduser,ou=SPECIAL,ou=USEROU,dc=example,dc=com
AuthLDAPBindPassword bindparseword
AuthzLDAPAuthoritative off
require ldap-group cn=Staff,ou=GROUPS,ou=USEROU,dc=example,dc=com
</Directory>

Once this is entered, save it. We need to now create the bind user. The orginisational units may change depending on your directory structure so you can go back into the httpd.conf file to change these accordingly.

Open Active Directory Users and Computers and navigate to where you want to create your bind user. In this example, we have an orginisational unit under the domain root called USEROU and the bind user in an OU called SPECIAL. Make the name of the user “binduser”. The first and last name can be “bind” and “user” respectivly, but make sure that the display name doesn’t include the space. Make the username binduser as well. As for the password, this is up to you. Make sure it reflects what is in the httpd.conf file.

Once this user is created, make sure that any changes in the location of the user is relflected in the httpd.conf file.

Als, before I forget, make sure that the hosts file is configured corectly. I have had some trouble when Apache doesn’t look up the name of the server using the name servers in the /etc/resolv.conf file. Add the server name to the hosts file as shown below. Of course, change your IP and name of the server to that of your orginisation.

echo “10.0.0.20 dc dc.example.com” >> /etc/hosts

Now start Apache

/etc/init.d/httpd restart

Now nagivate to the address of your web server and try to access the /secure directory. If it is successful you should be asked for a username and password. If you are a member of the “Staff” group or any group that you specified in the httpd.conf file you should see the “It Works!” text on the screen. If this is not the case have a look in the Apache log files for a clue. On thing that I find useful is changing the LogLevel to “debug” if there is nothing in the error logs that I can see. The most common error that there really is is getting the right syntax for the LDAP distinguished name. Double check that is is correct before looking at other errors.

July 19 2007 | Linux | No Comments »

NTLM with Apache + CentOS 5

NOTE: I have since used a different method for NTLM authentication. I found that this perl variant of NTLM had problems when a high load was put on the web server. There is a modification of the original auth_ntlm module to work with Apache 2.2 avaliable here

I thought I would document this as it is one of the most seemingly simplest but hardest things that I have done. There is a lot of documentation around, but nothing that I followed seemed to work.

First off we will want a fresh install of CentOS. For the test server I used 4.4, but the new production server the latest version, 5 was used. To keep the size down, don’t bother installing any extra packages. Keep it as minimal as possible, as we will install all the needed packages later.

Once you have booted into your new CentOS 5 system, we will want to update all the packages to their latest version. Login as root and enter the following command

yum update

Accept all the packages and let it download and install them. If you notice that the kernel gets updated, you will need to reboot your server in order for this change to take place. Otherwise, you wont need to reboot. Next we will install Apache

Install Apache using the following command at the shell

yum install httpd

Once this is installed, we need to install the appropriate development tools to be able to compile the perl NTLM module.

yum groupinstall “Development Tools”

This will take a while for the packages to download and for them to install. Once this is finished, you will need to download the perl module from. NOTE: We dont want the module Authen::perl::NTLM. This is included in the dag repository, found here. This repository is great and includes heaps of packages, something that you will probably want to add at a later date, but for now, we will need to build the module from source.

The module that we want is Apache2::AuthenNTLM. As far as I know it is not readily avaliable as an installable RPM so we will need to download the source and comple it manually.

cd /tmp

wget http://search.cpan.org/CPAN/authors/id/S/SP/SPEEVES/Apache2-AuthenNTLM-0.02.tar.gz

tar zxvf Apache2-AuthenNTLM-0.02.tar.gz

cd Apache2-AuthenNTLM-0.02

perl Makefile.pl

make install

You shouldn’t have any errors at compile time as long as you installed the “Development Tools” group package.

Thats all for the installation. All that needs to be done now is some configuration in the Apache config file. Firstly, keepalives need to be enabled. NTLM authentication simply won’t work without it. Open the file in Vim for editing.

vim /etc/httpd/conf/httpd.conf

Type in “/KeepAlive” still in Vim to search for that string (it is case sensitive as well)

/KeepAlive

Change this from Off to On. Press “a” to get into insert mode. Delete “Off” and replace it with “On”. Press the escape key and then “:x” and enter to save and exit. Now we need to set security on the file or directory which we want to protect with NTLM. This can be done with a .htaccess file or it can be programmed into the httpd.conf file or any vhost includes. For simplicity sake, we will make a directory called “secure” in the default webroot.

mkdir /var/www/htlm/secure

We now need to edit the httpd.conf file to include the following:

<Directory “/var/www/htlm/secure”>
Options Indexes
PerlAuthenHandler Apache2::AuthenNTLM
AuthType ntlm,basic
AuthName Secure Access
require valid-user
PerlAddVar ntdomain “YOURDOMAIN domaincontroller backupdomaincontroller”
PerlSetVar defaultdomain YOURDOMAIN
PerlSetVar splitdomainprefix 1
PerlSetVar ntlmdebug 0
PerlSetVar ntlmauthoritative off
</Directory>

This will now only let a user from your domain to access the contents of the secure directory.

Save the http.conf file and restart Apache. To test if authentication is working correctly, navigate you the secure directory at http://server.ip.addre.ss/secure. After you authenticate with a domain user and password, it should show a directory listing. Currently, there is nothing in the directory, but at least is demonstrates that NTLM is actually getting its auth data off Active Directory.

The next part is easy. All it involves is adding whatever site you configured Apache to use with authentication to the trusted zone in Internet Explorer. This can be done manually or configured as a GPO and deployed site wide. I noticed that even though IE detected I was in an intranet zone, it still failed to pass the NTLM auth to Apache and had a prompt for a user name and password.

Well thats about it. I hope this helps some others that just couldn’t get NTLM working correctly. Unfortunately, there is no group support with the Perl version on NTLM. There is a winbind NTLM module available that you can use that does provide some basic group support, but I couldn’t get this to work properly. Just remember that you need to add the site you are using to the trusted zone of IE. Once you go to the secured site, there should be a green tick on the bottom part of the window of IE. If this is the case, it is considered trusted.

July 09 2007 | Linux | 2 Comments »

Getting groups on the cheap with Apache/NTLM

I previously explained the setup for Apache with NTLM authentication. This is all well and good if you want to only authenticate with a few users in a manual htaccess file or if you want to only let members of the domain authenticate, but it not the greatest at getting group information.

A lot of the time groups are more useful than managing users and good practices say that permissions should practically be all based on groups. There are two ways to perform group authentication. The first way is based on the web application that you are restricting. If you have control over it and its coded in PHP, it can be hacked to enable tranparent authentication. This can be difficuilt, but not hard to perform if the application has been coded by yourself. The second method is based on a htaccess style method of authentication.

I opted for the second type of authentication. I wrote a script that got the users from Active Directory and then checked each one of they were a mamber of a specific group. It is a bit messy, but seemed the easiest and more secure.

// bind to the domain
include (“adLDAP.php”);
$ldap=new adLDAP();

// connect with the bind username and password
$ldap->authenticate(“binduser”,”binduserpassword”) or die(“Could not connect with the supplied user name and password\n”);

// List all users in the directory
$result=$ldap->all_users($include_desc = false, $search = “*”, $sorted = true);

// Setup the user string variable
$userstring = “require user “;

/* Run the loop checking which users are members of the staff group, add their name to the userstring variable */
for($i=0; $i < sizeof($result); $i++){
if(($ldap->user_ingroup($result[$i],”Staff”))== true){
$userstring = $userstring.$result[$i].” “;
}
}

// Write results to file
$fh = fopen(“/etc/httpd/vhost.d/example.com/secure”, ‘w’) or die(“cannot open file”);

$vhostfile1 = “<VirtualHost *:80>
DocumentRoot    \”/var/www/example.com/secure\”
ServerName      \”secure.example.com\”
ServerAlias     \”secure\”
ErrorLog logs/secure.example.com_error_log
CustomLog logs/secure.example.com_access_log common

<Directory \”/var/www/example.com/secure\”>
PerlAuthenHandler  Apache2::AuthenNTLM
AuthType ntlm,basic
AuthName test
“;

$vhostfile2 = ”
PerlAddVar ntdomain \”EXAMPLE   dc1.example.com dc2.example.com\”
PerlSetVar defaultdomain EXAMPLE
PerlSetVar splitdomainprefix 1
PerlSetVar ntlmdebug 1

</Directory>
</VirtualHost>
“;

fwrite($fh, $vhostfile1);
fwrite($fh, $userstring);
fwrite($fh, $vhostfile2);
fclose($fh);

// Restart Apache
system(“/bin/bash /etc/init.d/httpd restart”);

Most of the magic comes from the adldap API. You will need it to run this script and can download it from here. The other way involves listing the users in a group, but this outputs where the users are located in the directory and not simply their username.

July 09 2007 | Linux | No Comments »