Wednesday, December 31, 2008

Defending SSH Brute Force Attacks

I noticed allot of invalid user trying to login to my ssh box on the internet rather then changing my port or doing something else I opted to create an ssh script that denies all traffic coming from an IP who is trying to login with an invalid user. There are a couple requirements for the script. The primary IP needs to be on Eth0 interface and iptables has to be enabled on the box.

Here is the basic script that searches /var/log/messages for bad ssh attempts and adds a new iptables drop rule for each ip.

chmod 700
########## /root/Badssh.sh ############
!/bin/bash
#Badssh Audit Version 1.0
#Info-struct security system Inc.
#Authored Ryan Fawcett Gryanfawcett @ gmail dot com
TEMP=`grep sshd /var/log/messages | grep "Invalid user" | awk {'print $10'} | sort -u`;
echo "######Badssh.sh rules#########" >>/etc/rc.d/badssh-ips.sh;
for ip in $TEMP
do
echo "\$IPTABLES -A INPUT -i \$EXT_INT -s" $ip"/32 -j DROP" >>/etc/rc.d/badssh-ips.ssh;
done
sleep 2
/etc/rc.d/badssh-ips.ssh;

Here is the script that searches the logs and then appends the bad ips to the iptables rule set. You will need to clean up the script once in a while and I suggest setting up ssh keys to avoid locking yourself out by fat fingering your login.

chmod 700
####### /etc/rc.d/badssh-ips.sh #########
#!/bin/sh
# Ryan fawcett gryanfawcett at Gmail dot com 2001
# this script clears existing firewall rules and sets new rules
export EXT_IP="`/sbin/ifconfig eth0 | grep 'inet addr' | awk '{print $2}' | sed
-e 's/.*://'`"


###### Roots Crontab ########
0,15,30,45 * * * * /root/badssh.sh

Wednesday, December 24, 2008

Rsync Passwords and other Tidbits

I like Rsync allot and I tend to use it allot in daemon mode. I like to run it from Cron so that I know about every 1 to 5 min it back up certain files. Using it like this can be tricky b/c I also want to use some extra security, another thing is I don't want it to eat all up all my network bandwidth when syncing remotely with servers. So today we are going to Show you how to secure your Rsync with passwords, and limit bandwidth connections.

Lets start out with the basic config first.
This example is to rsync my pxe images directory.
#rsyncd.conf
uid = nobody
gid = nobody
use chroot = yes
max connections = 4
syslog facility = local5
pid file = /var/run/rsyncd.pid

[images]
path = /var/www/html/install/images
comment = whole linux image area (approx 6.1 GB)

Nothing special here just basic setup
But lets get fancy

Using Rsync Passwords

Here is the same config with rsync's own authentication configured.

#rsyncd.conf with auth
uid = nobody
gid = nobody
use chroot = yes
max connections = 4
syslog facility = local5
pid file = /var/run/rsyncd.pid

[images]
path = /var/www/html/install/images
comment = whole linux image area (approx 6.1 GB)
auth users = miuser nobody
secrets file = /etc/rsyncd.secrets

#rsyncd.secrets
miuser:passw0rd
nobody:passw0rd

Remember to make sure there is non-world readable on the secrets file
just to make sure and rest easy.

chmod 700 /etc/rsyncd.secrets

Now lets move to the client side we need to setup a password file so we can run this whole thing from a cronjob.

#pass
passw0rd

Just like secrets file you need to make it non-world readable

chmod 700 pass

Then give it a shot

rsync -avz --password-file=./pass miuser@yourserver.yourdomain.org::images/* /tftp

There you can add that to a cron job put it in a wrapper script or something else, now only authenticated clients can access rsync targets.

Bandwidth Limiting
Another handy option is to limit the bandwidth when rsyncing, b/c you don't want to saturate your pipe between Data centers or networks. From the man page it says

--bwlimit=KBPS
This option allows you to specify a maximum trans­
fer rate in kilobytes per second. This option is
most effective when using rsync with large files
(several megabytes and up). Due to the nature of
rsync transfers, blocks of data are sent, then if
rsync determines the transfer was too fast, it will
wait before sending the next data block. The result
is an average transfer rate equaling the specified
limit. A value of zero specifies no limit.

This trick is very useful here is an example of it

rsync -avz --bwlimit=300 --password-file=./pass miuser@yourserver.youdomain.org::images/* /tftp


Wednesday, December 17, 2008

RHEL 5 Simple Authentication via LDAP over TLS

One of the most interesting challenges I had in recent months is figuring out how to setup simple LDAP authentication via TLS on RHEL 5. I found little documentation for setting this up. I couldn’t find anything that took it from setting up a basic CA to testing and debugging issues you might run into. So the thought is I will be extremely useful to document this for other people
Some you need the following component to get this to work

Installing the packages

Creating a Certificate authority
  • Creating CA
  • Creating Server Certs
  • Testing and Debuging CA Certs
LDAP TLS configuration
  • Slapd.conf
  • Ldap.conf
  • Testing and Debugging
Schema
  • Adding the LDIF components to LDAP for OU people and adding a user.
  • Adding users
  • PAM/nscd configuring using LDAP tools
Nscd configuration
  • Auth-config-tui
Ready lets get started please Yum install the following packages
Yum install openldap*
Yum install system-config*

Ok great now lets move on to the next step.

CA Configuration
Unlike ever other document I found out there the CA.sh script was nowhere to be found on the /usr/share/openldap instead in RHEL 5 its been moved to /etc/pki/tls/misc/ this will create the Certificate authority in /etc/pki/CA because the default openssl configuration for RHEL 5 puts it there.

Run the script

Bash# ./CA -newca

Making CA certificate ...
Using configuration from /etc/pki/tls/openssl.cnf
Generating a 1024 bit RSA private key
..........................++++++
.........................++++++
writing new private key to './demoCA/private/./cakey.pem'
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]: example CA
Locality Name (eg, city) []: example SF
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []: I leave this blank just hit hard return
Common Name (eg, YOUR name) []:
Email Address []:.


Now your public key will be located in /etc/pki/CA/cacert.pem you will need this latter.

B/C of the screwy configuration of openssl.conf you need to change directory to
/etc/pki/tls/misc

Creating Sever Certificates
Now you need to create the server cert and key for the LDAP server to use.
Its really important that you setup the cn name to be the domain of your server not a FQD Host. Example example.com (Domain )


bash# openssl req -newkey rsa:1024 -nodes -keyout newreq.pem -out newreq.pem
Using configuration from /etc/pki/openssl.cnf
Generating a 1024 bit RSA private key
..............++++++
..........................++++++
writing new private key to 'newreq.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]: ]: example CA
Locality Name (eg, city) []: your city example SF
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []: any sub domain
Common Name (eg, YOUR name) []: enter server host name example server.domain.com
Email Address []: example ldapadmin@domain.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password :
An optional company name :.

It will produce newreq.pem in the current directory.
Now you need to sign the certificates

/etc/pki/tls/misc/CA.sh –sign
Using configuration from /etc/ssl/openssl.cnf
Enter PEM pass phrase:
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
countryName :PRINTABLE:'US'
stateOrProvinceName :PRINTABLE:'State'
localityName :PRINTABLE:'City'
organizationName :PRINTABLE:'Example Org'
organizationalUnitName:PRINTABLE:'Example yourdomain'
commonName :PRINTABLE:’server.youdomain.com'
emailAddress :IA5STRING:'ldap@myserver.com'
Certificate is to be certified until Apr 10 18:58:58 2004 GMT (365 days)
Sign the certificate? [y/n]:y

Now you need to take the newreq.pem and newcert.pem and move them with the CA cert to cacerts place for ldap to read the certs from.

Cp /etc/pki/CA/cacert.pem /etc/openldap/cacerts/
Cp /etc/pki/tls/misc/newcert.pem /etc/openldap/cacerts/servercrt.pem
Cp /etc/pki/tls/misc/newreq.pem /etc/openldap/cacerts/serverkey.pem

Now lets test the certs to make sure everything is good before we go installing them.

openssl verify -CAfile ./cacert.pem servercrt.pem
servercrt.pem: OK

Distribute Cacert.pem to all the client machines

Scp /etc/openldap/cacerts/cacert.pem user@host:/etc/openldap/cacerts/

Configuring Slapd.conf
This is the configuration for the server and
This part is kind of tricky but I will give you some help on debugging so if you run into issues let me know.

Uncomment or change the following lines.

Allow bind_v2

Base dc=yourdomain,dc=org
TLSCACertificateFile /etc/openldap/cacerts/cacert.pem
TLSCertificateFile /etc/openldap/cacerts/servercrt.pem
TLSCertificateKeyFile /etc/openldap/cacerts/serverkey.pem
access to *
by self write
by users read
by anonymous auth
database bdb
suffix "dc=yourdomain,dc=org"
binddn “cn=Manager,dc=yourdomain,dc=org”
bindpw secret
tls_cacertdir /etc/openldap/cacerts
tls_CACERT /etc/openldap/cacerts/cacert.pem
tls_REQCERT demand
ssl start_tls
uri ldap://yourserver.yourdomain.org/

Now restart ldap

Service ldap restart


Configure LDAP Client ldap.conf
Now on the server as well as client you should configure ldap.conf
This is the client configuration stored in /etc/ldap.conf
Uncomment or change the following lines

base dc=yourdomain,dc=org

binddn cn=Manager,dc=yourdomain,dc=org
bindpw secret
ssl start_tls
tls_checkpeer yes
tls_cacertfile /etc/openldap/cacerts/cacert.pem
tls_cacertdir /etc/openldap/cacerts/

Testing the configuration / Debugging
Lets test to make sure the SSL is working.

openssl s_client -connect server.yourdomain.org:636 -CAfile /etc/openldap/cacerts/cacert.pem

You should get something like this.

SSL-Session:
Protocol : TLSv1
Cipher : AES256-SHA
Session-ID: 69E38A9BFB51A39EB174B95974FA42D37E101F1F65CF396DC86AB088C9910F58
Session-ID-ctx:
Master-Key: E8CA2A9EBB8258F0A7A39C4167C8190C96DBCE835BD88A2DE44ABA05425B67276203C877464656022A4D65879438E31A
Key-Arg : None
Krb5 Principal: None
Start Time: 1229577041
Timeout : 300 (sec)
Verify return code: 0 (ok)

This verifies that the CA Certs are working and clients can connect via TLS.

ldapsearch -x -b "dc=yourdomain,dc=org" -D "cn=Manager,dc=yourdomain,dc=org" '(objectclass=*)' -H ldap://ldap.myserver.org -W -ZZ


The password is the password in your slapd.conf in this case secret.

The –W and –ZZ Forces TLS with password authentication if it says it fails to connect run the following command to see the reason.

ldapsearch -d -1 -x -b "dc=yourdomain,dc=org" -D "cn=Manager,dc=yourdomain,dc=org" '(objectclass=*)' -H ldap://ldap.myserver.org -W –ZZ

The –d -1 tell ldapsearch to go into debug mode with debug level -1
This is handy to figure out why it doesn’t work. Then you can debug from there.


Schema Changes
Changes the schema is kinda of important allows for you to use the migrate scripts.
You need to add the people.ldif

dn: ou=people,dc=yourdomain,dc=org
objectClass: organizationalUnit
ou: people

ldapadd –x –D “cn=Manager,dc=yourdomain,dc=org” –W –f people.ldif

Adding Users
Adding users is pretty easy do the normal useradd procedure on the ldap server in Unix and then grep out the password and run the migration script.

Useradd username
Passwd password
grep username /etc/passwd >username.passwd
/usr/share/openladp/migration/migrate_passwd username.passwd usrname.ldif

Now all you have to do is add the user.ldif to the directory

Ldapadd –x –D “cn=Manager,dc=yourdomain.,dc=org” –W –f username.ldif

Restart ldap on the server

Service Ldap restart


Configuring PAM and nscd Deamon

The quickest way to get things running is to cop the ldap.conf file to the client and make sure you have the CA cert in the right place and the rootdn and rootpasswd set in the ldap.conf.

Then simply run the authconfig-tui from the command line.
Under user information
Select use LDAP

Under Authentication select
Select USE Shadow Password
Select USE LDAP Authentication
Select Local Authorization is sufficient ( this way you don’t lock yourself out. )

Next Click Next
Select TLS
Server: ldap://yourserver.yourdomain.org/
Dc=yourdomain,dc=org
Click ok.

Now restart nscd
Service nscd restart
Check /var/log/messages to make sure that you don’t get any binding errors
Login with the LDAP user name and password

There you go. If you have any problems with the instructions email me at gryanfawcett at gmail dot com.







Wednesday, December 10, 2008

RPM FOO Creating RPMS from Tar files

Working in Linux shops for years, one of the most challenging obstacles is coming out with a way to manage and maintain standard software and configurations across multiple servers. Using RPMS To distribute configurations via YUM and automated Installs via Kick-start. Is a good system management practice and has many advantages over other distribution methods.

Most of these examples, I list below don't need any pre or post scripts to deploy but just a good way to check versions, track, install and remove packages.

The following are some of the uses I use custom RPMS for.

  • SSH Keys
  • Web Site Releases
  • Standard System Configurations
  • And a million other things.

The advantages to using RPMS are numerous and ,well, lets just say it brings a lot more sanity to a chaotic world of system administration. RPM's most notable purpose is to install and back out of releases and configurations in a structured and organized manner.

But then again, its said that building and maintaining RPM packages has a high learning curve, and building RPM spec files is somewhat of a black art.

So here are the simple method to build your own RPMS.

On a RHEL 5 or CentOS 5 box (Probably works on RHEL 4 as well but I haven't tested it).

1. Yum install rpm-build
2. Tar up the files from the root directory ( and I don't mean /root )
3. Copy and Paste the script from below and save the script named bintar2rpm.
4. chmod 755 bintar2rpm
5. Execute the following command ./bintar2rpm Example.tar
6. Now answer the questions Summary of the rpm package (aka what is it)
7. Name of the rpm example.rpm
8. Major Version meaning 1 or 2 (Numeric input )
9. Release 0 or 1 ( So with the Major Version being 1 or 2 it will be 1.0 or 2.1)
10. License its distributed under: Privately, FreeBSD or GPL V2/V3

Sit back and watch it build the RPM for you on the hardware platform you are on.
It usually puts it the rpm in /usr/src/RPMS/$ARCH

Thanks to Bart Scaefer to a good patch that makes this work more like it was designed to.
As well as he added gzip support for the tar files.

There you go an RPM package in under a minute.


#!/usr/bin/perl
#Created by G. Ran Fawcett of Info-struct Systems
#Edited to support gzip'd tar files and alternate install path
# by Bart Schaefer
#For support and assistance contact gryanfawcett at gmail dot com
#Licnced under GPL v3
#Version 1.0-b
# Reason for using all system calls is to make this portable without any additional modules
if ( ! -e '/usr/bin/rpmbuild')
{
print "Missing Build Tools or Build Environment please install rpm-build";
exit 1;
}

if ( $ARGV[0] eq '' )
{
print "Error Missing tar file: try -h for usage\n";
exit 1;
}


if ($ARGV[0] eq '-h')
{
print "bintar2rpm Package by G. Ryan Fawcett gryanfawcett at gmail dot com\n";
print "Usage: bintar2rpm example.tar installdir\n";
exit 1;
}

$BuildRoot = "/tmp/bintar2rpm$$";

$TarPackage = $ARGV[0];
if ( $TarPackage =~ /gz$/ )
{
$tarOpts = 'zf';
}
else
{
$tarOpts = 'f';
}

$ExtractTo = $ARGV[1] || "/";
if ( $ExtractTo !~ m:^/: )
{
print "Install directory must be a full path from the root\n";
exit 1;
}

system("mkdir -p $BuildRoot$ExtractTo");
@FileList = `tar -C $BuildRoot$ExtractTo -xv$tarOpts $TarPackage 2>/dev/null`;

if ( $ExtractTo !~ m:/$: )
{
$ExtractTo .= "/";
}

print "Summary: ";
$Summary = %3CSTDIN%3E%0A ;
chomp $Summary;
print "Name: ";
$Name = ;
chomp $Name;
print "Version: ";
$Version = ;
chomp $Version;
print "Release: ";
$Release = ;
chomp $Release;
print "License: ";
$License = ;
chomp $License;
$Group = 'Application/Production';
$ARCH = `uname -i`;
chomp $ARCH;

$FileOutput = "$Name" . "-" . "$Version" . "-" . "$Release" . "\." . "$ARCH" . "\.spec";

open(SpecFile, ">$FileOutput");
print SpecFile "Name: $Name\n";
print SpecFile "Summary: $Summary\n";
print SpecFile "Version: $Version\n";
print SpecFile "Release: $Release\n";
print SpecFile "License: $License\n";
print SpecFile "Group: $Group\n";
print SpecFile "Source: $TarPackage\n";
print SpecFile "Requires: /bin/sh\n";
print SpecFile "\%Description\n";
print SpecFile "The following is $Name version $Version\n";
print Specfile "\n\%prep\n";
print SpecFile "\n\%setup\n";
print SpecFile "\n\%files\n";

for $_ (@FileList)
{
$_ =~ s:^/::;
print SpecFile "$ExtractTo$_";
}
print SpecFile"\n\%post\n";
close(Specfile);

system("cp $FileOutput /usr/src/redhat/SPECS");
system("cp $TarPackage /usr/src/redhat/SOURCES");
system("rpmbuild --buildroot=$BuildRoot -bb /usr/src/redhat/SPECS/$FileOutput");
print "Cleaning up ...\n";
system("rm -rf $BuildRoot");