Sunday, August 26, 2012

Part 2: Adding the firewall rules

In part two of this series we're going to discuss adding firewall rules to the router.  Everyone knows that adding ingress (or incoming) firewall rules is important to securing your network.  However, the same can be said for adding egress rules for traffic leaving your network.  For instance, aside from an email server, no client should ever send traffic to the Internet via TCP port 25.  If you see traffic like this, it could mean that you have an infected computer within your network.  Egress firewall rules, along with logging of those rules, will help track down problems before it gets out of hand.  

First lets up the ingress rules to protect the router from incoming traffic we do not want.
    iptables -A INPUT -m state --state INVALID -j DROP
    iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    iptables -A INPUT -s -p icmp -j ACCEPT
    iptables -A INPUT -i lo -j ACCEPT
    iptables -A INPUT -s -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
    iptables -A INPUT -i eth0 -j LOG --log-prefix " *** IPTABLES DENY IN *** "
    iptables -A INPUT -j REJECT

The first rule allows us to configure the stateful firewall.  Any connections that are already established on the server is allowed through, new connections will not be allowed by this line.  The second rule allows for internal clients to ping their default gateway.  Third rule is VERY IMPORTANT as it allows server traffic to be allowed on the loopback interface.  Most Linux communication including X and service daemons use the loopback for internal communication.  If you do not allow this rule then you could kill everything.  The fourth line allows internal traffic to connect through SSH for remote administration.  We can further restrict SSH by only allowing SSH keys, or if you have a monitor hooked up to the router you could skip this rule altogether.  And the last rule blocks all other incoming traffic to the router.

Now lets setup the egress rules on the router.  To do this, we will use the forward table in iptables.  This is used to forward traffic from one interface to another.
    iptables -A FORWARD -m state --state INVALID -j DROP
    iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    iptables -A FORWARD -i eth1 -p tcp -m tcp --dport 22 -j ACCEPT
    iptables -A FORWARD -i eth1 -p tcp -m tcp --dport 80 -j ACCEPT
    iptables -A FORWARD -i eth1 -p tcp -m tcp --dport 443 -j ACCEPT
    iptables -A FORWARD -i eth1 -p tcp -m tcp --dport 465 -j ACCEPT
    iptables -A FORWARD -i eth1 -p tcp -m tcp --dport 587 -j ACCEPT
    iptables -A FORWARD -i eth1 -p tcp -m tcp --dport 993 -j ACCEPT
    iptables -A FORWARD -i eth1 -j LOG --log-prefix " *** IPTABLES DENY OUT *** "
    iptables -A FORWARD -j REJECT
    iptables -A FORWARD -s -i eth0 -j DROP

The first rule for this is similar to the first rule to the last set.  The next set of rules allow internal clients to connect to any server on the Internet using SSH, HTTP/HTTPS, and email.  The last few lines are important as first we log dropped packets, then drop packets that do not meet the lines above, and then an anti-spoofing line.  We will talk about logging in a minute, I just want to point out one additional thing.  Be extremely careful when creating egress firewall rules as this will break things.  For instance, if someone needs to establish an outgoing VPN connection then you will need to add those rules in or it will not work.

To get IPTABLES to log dropped packets to a log file, we use rsyslog.  In the /etc/rsyslog.conf file add the following lines:
    :msg,startswith," *** IPTABLES DENY OUT *** " /var/log/iptables-egress
    :msg,startswith," *** IPTABLES DENY IN *** " /var/log/iptables-ingress
Now start the rsyslog daemon and restart iptables and you'll be all set.

PyMyDB Backup 0.5.1

The first version of PyMyDB Backup has been released and is based on Python 2.4.3. This is a Python script that will back up your MySQL databases, calculate the size of the backed up files, tarball and compress the contents, then email the results.
To use:
    Download the EPEL RPM which can be found at:
     Install pymydb-0.5.1-1.noarch.rpm which can be found at: GitHub
         This script creates the necessary directories and user account
     After installation, there will be two scripts placed in /usr/local/bin which are and
     Run the script, this will configure the script
         Logs into the MySQL server
         Creates the backup user, sets a password, and gives him select and lock tables privileges
         Configures the email settings
     Change the permissions on the script
         chown root.pymydb
     Add the script into cron and make sure to add a password for the system user
 You can download it at my GitHub page

Friday, August 3, 2012

Setting up NAT with CentOS/Red Hat 6

​This will be part 1 in a series of configuring CentOS/Red Hat 6 as a secured firewall. Though I am a huge fan of pfSense (which can be found here pfSense), I wanted to build my own from scratch. So, the first part of this series will consist of setting up PAT (or NAT overload for the Cisco geeks) on Linux.
The first step is to configure the network cards.  In this scenario we will use eth0 as the WAN connection and eth1 as the LAN connection.  Refer to the diagram below
 | ISP - | <--- | eth0(WAN) - | --- NAT Server --- | eth1(LAN) - | ---> Internal Network
Edit both the ifcfg-eth0 and the ifcfg-eth1 files located in /etc/sysconfig/network-scripts/, make sure both of the network cards are set to BOOTPROTO="static".
The second step is to setup IP forwarding which can be done by editing the /etc/sysctl.conf file and adding
    net.ipv4.ip_forward = 1
You can then either reload the server or issue the 'sysctl -p' command. Once that command is run, you will see the output of the command and you should see 'net.ipv4.ip_forward = 1' in the output. You can also verify by running 'cat /proc/sys/net/ipv4/ip_forward' and it will return a '1'. If it returns a 0 then the command did not run correctly and you need to try again.
The last step is to set up masquerade with IPTABLES. As eth0 is your outside (or WAN) connection, run
    iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Connect a laptop to the eth1 NIC with a crossover cable, and statically set the IP address to with the default gateway of  You should now be able to ping out of the LAN to the Internet. If successful run,
    service iptables save
which will save the command to the /etc/sysconfig/iptables file when either the service or the server is reloaded.

Saturday, June 9, 2012

Mounting a USB Device In a Xen Guest

​Mounting a USB device
 Attach the USB device to the Dom0 and run ‘dmesg’ to see if the device attached
 Run ‘fdisk -l’ to see if the drive is partitioned the way you want it
 For instance:
[[email protected] ~]# fdisk -l /dev/sdc
Disk /dev/sdc: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
dev/sdc1 1 121601 976760001 8e Linux LVM
Now find a drive letter that is not being used on the DomU, in this instance we’ll use /dev/sde
To attach the USB device to the DomU run the following command
    xm block-attach exampledomu phy:/dev/sdc sde w
You should now see the device on the DomU, run either ‘dmesg’ or ‘fdisk -l’ to verify
Mount the device as normal
    mount /dev/sde1 /mnt/usb
Unmounting the device
You first need to get the device id number from the block list. Do this by running:
    xm block-list exampledomu
This will return:
    Vdev BE handle state evt-ch ring-ref BE-path
    51712 0 0 4 9 8 /local/domain/0/backend/tap/23/51712
    2176 0 0 4 10 1338 /local/domain/0/backend/vbd/23/2176
The number you need to use to remove the device is 2176
Unmount the USB device from the DomU
     umount /mnt/usb

 Now on the Dom0 run:
     xm block-detach exampledomu 2176
 You may now remove the USB device

Getting Linksys AE2500 to work with Fedora 17

​In order to get the AE2500 wireless USB adapter to work you must install ndiswrapper. First, the ndiswrapper-1.57 version is not compatible with the 3.3 or 3.4 version of the Linux kernel so you must install the ndiswrapper-1.58rc1 which is still in test as of this writing. Next, download the AE2500 Windows XP drivers from the Linksys website ( Link ). Unzip the drivers into a directory and load the bcmwlhigh5.inf file into ndis. Once this is done, you can run the 'ndiswrapper -l' command to verify that it is installed correctly. Finally, run 'modprobe ndiswrapper' to load the driver into the kernel. Once this is complete you should see the wireless USB device come up as wlan0 and ready for use.

Saturday, June 2, 2012

MySQL Backup Script

I needed a place to host my scripts, so I opened an account on GitHub. If you are unaware of what GitHub is, its a great place to publish code to the public by using Git; they also offer private hosting for a fee. Even if you do not have a need for this I recommend looking through the site as its a great place to view open source projects.
There are a lot of examples and scripts out on the Internet to automate MySQL backups but not a whole lot written in Python. This was developed to use in a MySQL replication environment and should be run on the slave server. This is an optimal solution as backup’s can run without affecting production. The script dumps each database individually, calculates the size of the sql backup, tarball them up, and emails a log when its done.
To run this the MySQLdb module must be installed on the server. You should also create a user specifically designed to run backups. You can effectively do this by running:
    grant select, lock tables on *.* to [email protected]'localhost' identified by 'password';
The password is stored in base64 format. To encrypt the password for use in the script, run the following command within the Python terminal:
    >>> from base64 import b64encode as encode
    >>> encode("password")
Though this is not the most secure way to encrypt a password to use within a script, it will prevent shoulder surfers.

Friday, March 9, 2012

RHEL/CentOS Server Security

As a part of the sys admin's job, it is important to take a few extra minutes to go through and properly secure a newly installed Linux server. These steps include enabling SELinux on the machine, configuring the firewall, and setting user permissions. There are however additional steps one should take in order to secure their server. One would be to tune and secure kernel parameters, set limits on kernel dumps, prevent IPv6 from loading if you company is not using it, and turning off unnecessary services.

First, lets take a look at configuring kernel parameters to prevent network based attacks. These include disallowing intruders to alter routing tables and source routed packets, preventing an intruder from configuring the server to become a router, and turning on reverse path filtering. To change these settings edit the /etc/sysctl.conf file and enter:
    net.ipv4.conf.all.accept_source_route = 0 
    net.ipv4.conf.all.accept_redirects = 0 
    net.ipv4.conf.all.secure_redirects = 0 
    net.ipv4.conf.all.log_martians = 1 
    net.ipv4.conf.default.accept_source_route = 0 
    net.ipv4.conf.default.accept_redirects = 0 
    net.ipv4.conf.default.secure_redirects = 0 
    net.ipv4.icmp_echo_ignore_broadcasts = 1 
    net.ipv4.icmp_ignore_bogus_error_messages = 1 
    net.ipv4.tcp_syncookies = 1 
    net.ipv4.conf.all.rp_filter = 1 
   net.ipv4.conf.default.rp_filter = 1 

If you are currently running IPv6 at your company, here are a few kernel parameters to prevent network based attacks:
    net.ipv6.conf.default.router_solicitations = 0 
    net.ipv6.conf.default.accept_ra_rtr_pref = 0 
    net.ipv6.conf.default.accept_ra_pinfo = 0 
    net.ipv6.conf.default.accept_ra_defrtr = 0 
    net.ipv6.conf.default.autoconf = 0 
    net.ipv6.conf.default.dad_transmits = 0 
    net.ipv6.conf.default.max_addresses = 1 

To make these settings effective without rebooting the server type sysctl -p 

We can go a step further by disabling unused network functions such as IPv6 and prevent self assigned addressing.

To detect whether or not IPv6 is running on a server type: ifconfig | grep inet6 which will return:
    inet6 addr: fe80::240:5ff:fe32:ef19/64 Scope:Link 
    inet6 addr: ::1/128 Scope:Host 
    inet6 addr: fe80::200:ff:fe00:0/64 Scope:Link 
To prevent IPv6 from loading, run the following command:
    echo install ipv6 /bin/true > /etc/modprobe.d/ipv6 
Then add the following lines to /etc/sysconfig/network:
This will deactivate the IPv6 protocol from running on the server.

To prevent self assigned addressing on network cards, open the /etc/sysconfig/network file and add:
Server security 
Turning off the ability to create core dumps is important as intruders can use this to gather information about running services and configurations in order to exploit them. To do so, edit the /etc/security/limits.conf file and insert:
    * hard core 0 
 We should also prevent setuid programs from creating these as well:
    sysctl -w fs.suid_dumpable=0 

There are also built in kernel features which can help protect against buffer overflow attacks. These features are turned on by default, however these kernel parameters should be enabled in case they have been turned off:
    sysctl -w kernel.exec-shield=1 
    sysctl -w kernel.randomize_va_space=1 
These settings ensure randomization of the stack and memory regions, which are refereed to as the ExecShield.

There are many services which are running on a default installation which include cups, sendmail, isdn, bluetooth, and many others. If these services are not being used on the server then they should be turned off and configured not to start up on a reboot. To do so we can run the following bash script:
for i in acpid autofs avahi-daemon luetooth cups firstboot gpm hidd ip6tables sendmail exim xfs xinetd yum-updatesd rhnsd pcscd readahead_early readahead_later apmd hplip isdn ip6tables mcstrans 
    service $i stop 
    chkconfig $i off 

Your services will vary depending on the installation. We should also ensure that X does not run on reboot, placing the server in run level three. To do so, edit the /etc/inittab file and change id:5:initdefault: to id:3:initdefault:

Saturday, March 3, 2012

GPG Keys

​GnuPG is used to encrypt and sign email messages and files. First you need to create the GPG key:
Generating Keys
$ gpg --gen-key
Select option 5 for RSA and then type the encryption level.
Please select what kind of key you want:
(1) DSA and Elgamal (default)
(2) DSA (sign only)
(5) RSA (sign only)
Your selection? 5
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
= key expires in n days
w = key expires in n weeks
m = key expires in n months
y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y
Now enter your personal information
Real name: Jason Brown
Email address: [email protected]
Comment: Example
You selected this USER-ID:
"Jason Brown (Example) "
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key 7C11053D marked as ultimately trusted
public and secret key created and signed.
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 4 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 4u
pub 4096R/7C11053D 2009-10-12
Key fingerprint = EE6B C53F A665 593C 3607 FEE1 F984 2AF9 7C11 053D
uid Jason Brown (Example)
As stated in the option menu, this key is only generated to sign email or files and cannot be used to encrypt. You now have to edit the key that was just generated to use it for encryption.
$ gpg --edit-key [email protected]
pub 4096R/7C11053D created: 2009-10-12 expires: never usage: SC
trust: ultimate validity: ultimate
[ultimate] (1). Jason Brown (Example)
Command> addkey
You need a passphrase to unlock the secret key for
user: "Jason Brown (Example) "
4096-bit RSA key, ID 7C11053D, created 2009-10-12
Enter in your passphrase and then select option 6 for 'RSA (encrypt only)'. It will then ask for a key size and key expiration, use the same settings as in the first section. Once complete you will have a new key for encryption.
pub 4096R/7C11053D created: 2009-10-12 expires: never usage: SC
trust: ultimate validity: ultimate
sub 4096R/55D59203 created: 2009-10-12 expires: never usage: E
[ultimate] (1). Jason Brown (Example)
Now type save to exit:
Command> save
Your new key is now ready to be uploaded to the key repository servers.
$ gpg --keyserver --send-key [email protected]
GPG Key Backup
Once your keys have been generated, you will need to export both the public and private keys and store them for safe keeping. To export your public key:
$ gpg --export -a [email protected] > example-pub.key
And the private key:
$ gpg --export-secret-key -a [email protected] > example-priv.key
You can then create a tar backup of these two keys and encrypt them with a passphrase.
$ tar -cvf gpgkeys.tar example-priv.key example-pub.key
$ gpg -c --cipher-algo aes256 gpgkeys.tar
Then enter in a strong password. This will allow you to retrieve your keys if you do not have your public/private key pair installed on a machine. Once this is done you will need to securely delete your keys leaving just the tarball. This is important as someone can compromise your keys.
$ for i in gpgkeys.tar example-priv.key example-pub.key
>shred -n 100 -z -u -v $i
Retrieving Public Keys
To search for a persons key type:
$ gpg --search-keys [email protected]
As this is an example and a fake email address, this will not return any results. Had this been a real address you will see a list of email addresses with numbers along the side. To request the public key of that person, type the number and hit 'enter' and it will retreive the public.
Encrypting Files to Other Users
To encrypt a file to a different user you must first have that users public key. To check type:
$ gpg --list-keys
pub 4096R/7C11053D 2009-10-12
uid Jason Brown (Example)
sub 4096R/55D59203 2009-10-12
I will encrypt a file to myself. The '-e' option is to tell it to encrypt and the '-r' is the recipient or public key of the person you want to give the file to.
$ gpg -e -r [email protected] ssn.txt
To decrypt the file, the receipient must have their public key installed on the machine. Then type:
$ gpg --output ssn.txt --decrypt ssn.txt.gpg
Where '--output' is the name of the decrypted file and '--decrypt' is the file being decrypted.
You may also want to digitally sign the file you are encrypting, to do so type:
$ gpg --detach-sig ssn.txt.gpg
And to verify the signature file:
$ gpg --verify ssn.txt.gpg
gpg: Signature made Mon 12 Oct 2009 02:21:26 PM EDT using DSA key ID 7C11053D
gpg: Good signature from "Jason Brown (Example) "