Showing posts with label Linux / UNIX. Show all posts
Showing posts with label Linux / UNIX. Show all posts

Dec 2, 2009

Networking : network isolation with iptables and brctl


This is one of the first problems I had to solve in my career : the goal is to isolate a part of an existing network for any reason. Let's say your network is configured 192.168.0.0/16 and you cannot isolate with the use of VLANs (either you don't have compliant equipment, either you cannot do it on your architecture, ...).

The solution is to use a Linux bridge and filter packets with iptables.

Have a look at the graphic at the beginning of this post : this is what I'll implement with the following scripts. So let's suppose you want to isolate a group of client machines with their own servers (UNIX and Windows servers).
Considering this, there are three things to do :

  • Give access to the servers and client machines from admin machines
  • Give access to internet, e-mailing, FTP, etc to isolated machines
  • Give access to some services (license, Samba,...) from machines outside the isolated network

In order to do that, prepare a machine with 2 Ethernet cards, install any distro you want on it (i like CentOS but any Debian-like or Suse or any Linux is fine too). Once your this installed, verify that your 2 Ethernet controllers are recognized :

lsmod
lspci
ifconfig -a

The ifconfig -a command should have 2 ethernet interfaces (eth0 and eth1 usually), if not get the good linux module for your network card !

Now, install bridge utilities :
apt-get install bridge-utils #on Debians
yum install bridge-utils #on RHEL / CentOS / Fedora

Let's configure the brigde now. Here is the script that you'll have to put in /etc/init.d and link to /etc/rc5.d/ according to your distro (see /etc/runlevel for current runlevel and your distro doc for running a script at startup).
#!/bin/sh
#
# Start and stop Network bridge
#
case "$1" in
start)
ifconfig eth0 0.0.0.0 promisc
ifconfig eth1 0.0.0.0 promisc

brctl addbr pont
brctl addif pont eth0
brctl addif pont eth1

ifconfig pont 192.168.231.50 netmask 255.255.255.0
route add default gw 192.168.231.254
;;
stop)
brctl delif pont eth0
brctl delif pont eth1
brctl delbr pont
;;
stat)
brctl showstp
;;
*)
echo "Usage : /etc/init.d/brigde start | stop | stat"
;;
esac

We configure the bridge with the 192.168.231.50 IP address, and add to it our 2 ethernet cards.

Now the bridge is up and running let's focus on the packet filtering. As I said, iptables will help up do that, as long as we know source IP, dest IP, proto (tcp, udp,..) and port. Here is the firewalling script, to be put in /etc/init.d :

#!/bin/sh
#
# Start and stop Firewall
#
case "$1" in
start)
PATH="/usr/sbin:$PATH"

#We flush tables
iptables -F
#We erase all user tables
iptables -X

#Default rules : Deny all access
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

#Let's log what goes through our firewall
iptables -t filter -A INPUT -j LOG --log-level notice
iptables -t filter -A OUTPUT -j LOG --log-level notice
iptables -t filter -A FORWARD -j LOG --log-level notice

#Admin machines, access the firewall, and UNIX and Windows servers
awk '{print $1}' /etc/machines_admin | while read ligne
do
#We accept connnection from admin machines to our firewall
iptables -A INPUT --source $ligne -p tcp --dport ssh -j ACCEPT
iptables -A OUTPUT --destination $ligne -p tcp --sport ssh -j ACCEPT
#Connections from admin machines to UNIX server : ping and SSH
iptables -A FORWARD --source $ligne --destination 192.168.100.102 -p icmp -j ACCEPT
iptables -A FORWARD --source 192.168.100.102 --destination $ligne -p icmp -j ACCEPT
iptables -A FORWARD --source $ligne --destination 192.168.100.102 -p tcp --dport ssh -j ACCEPT
iptables -A FORWARD --source 192.168.100.102 --destination $ligne -p tcp --sport ssh -j ACCEPT
#Connections from admns to Windows server : ping and Dameware remote control
iptables -A FORWARD --source $ligne --destination 192.168.100.100 -p icmp -j ACCEPT
iptables -A FORWARD --source 192.168.100.100 --destination $ligne -p icmp -j ACCEPT
iptables -A FORWARD --source $ligne --destination 192.168.100.100 -p tcp --dport 6129 -j ACCEPT
iptables -A FORWARD --source 192.168.100.100 --destination $ligne -p tcp --sport 6129 -j ACCEPT
#Add here any rule you need for admin machines
done

#Machines behind the firewall should accees mail server, internet, and an accees to a FTP server
awk '{print $1}' /etc/machines_client | while read ligne
do
#Client machines ger accees to mail server (smtp and imap), proxy (tcp 8080), and LDAP on the mail server (tcp/389)
iptables -A FORWARD --source $ligne --destination 192.168.110.97 -p tcp --dport 8080 -j ACCEPT
iptables -A FORWARD --source 192.168.110.97 --destination $ligne -p tcp --sport 8080 -j ACCEPT
iptables -A FORWARD --source $ligne --destination 192.168.110.112 -p tcp --dport 143 -j ACCEPT
iptables -A FORWARD --source 192.168.110.112 --destination $ligne -p tcp --sport 143 -j ACCEPT
iptables -A FORWARD --source $ligne --destination 192.168.110.112 -p tcp --dport 25 -j ACCEPT
iptables -A FORWARD --source 192.168.110.112 --destination $ligne -p tcp --sport 25 -j ACCEPT
iptables -A FORWARD --source $ligne --destination 192.168.110.112 -p tcp --dport 389 -j ACCEPT
iptables -A FORWARD --source 192.168.110.112 --destination $ligne -p tcp --sport 389 -j ACCEPT
#We authorize client machines to acceess a FTP server
iptables -A FORWARD --source $ligne --destination 10.243.0.225 -p tcp --dport 21 -j ACCEPT
iptables -A FORWARD --source 10.243.0.225 --destination $ligne -p tcp --sport 21 -j ACCEPT
iptables -A FORWARD --source $ligne --destination 10.243.0.225 -p tcp --dport 20 -j ACCEPT
iptables -A FORWARD --source 10.243.0.225 --destination $ligne -p tcp --sport 20 -j ACCEPT
#From admin machines to client machines, we let authorize ping and Dameware remote control
awk '{print $1}' /etc/machines_admin | while read admin
do
iptables -A FORWARD --source $admin --destination $ligne -p tcp --dport 6129 -j ACCEPT
iptables -A FORWARD --source $ligne --destination $admin -p tcp --sport 6129 -j ACCEPT
iptables -A FORWARD --source $admin --destination $ligne -p icmp -j ACCEPT
iptables -A FORWARD --source $ligne --destination $admin -p icmp -j ACCEPT
done
#Add here any rules you need for client machines
done

;;
stop)
iptables -F
iptables -X
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
;;
stat)
iptables -L
;;
*)
echo "Usage : /etc/init.d/firewall start | stop | status"
;;
esac

Note that we use 2 files for declaring admin and client machines. These 2 files should be same format as /etc/hosts, meaning for ex for /etc/machines_admin:
192.168.100.45 PC329
192.168.100.222 PC771

Same thing for /etc/machines_client.

Now you have a working, logging firewall/bridge :)

Have fun !

Nov 30, 2009

RHEL & CentOS automatic install Kickstart


I use Kickstart in order to install automatically RHEL (3, 4, 5, 32 or 64 bit) and CentOS from an image shared on the network (NFS).

You can completely automatize the method I describe by adding a DHCP/BOOTP server on which you install a boot image. I do not use that because of already having several networks, all with their own DHCP. I use a bootable image of RHEL and then start with this line on the GRUB :

linux ks=nfs:192.168.xx.xx:/path/to/your/kickstart
The advantages of this method are :

  • Nothing to do during the install, meaning time for other things ;p
  • You can customize the default RHEL or CentOS install with the post-install script
  • Greatest speed ever !!! Twice or three times faster than installing with DVD or CD, as long as your network is correct (100Mb).

So, first step is to create ISO images of your favorite distro. For that use dd or mkisofs :
dd if=/dev/dvd of=image.iso
mkisofs -R -J -o image.iso /mnt/cdrom


Then, share these images (i have on per architecture and distro) on a NFS server.

Now the most important, the Kickstart file :
# System authorization information
auth --useshadow --enablemd5 --enablenis --nisdomain=mydomain --nisserver=192.168.xxx.xxx
# License RHEL
key xxxxxxxxxxxxxx # put here youy license key
# System bootloader configuration
bootloader --location=mbr
# Clear the Master Boot Record
zerombr
# Partition clearing information
clearpart --all --initlabel
# Use graphical install
graphical
# Firewall configuration
firewall --disabled
# Run the Setup Agent on first boot
firstboot --disable
# System keyboard
keyboard fr-latin1
# System language
lang fr_FR
# Installation logging level
logging --level=debug
#We make a network install from NFS Server
nfs --server=192.168.xxx.xxx --dir=/path/to/your/isos/
# Network information
network --bootproto=dhcp --device=eth0 --onboot=on --mtu=4500
# Reboot after installation
reboot
#Root password
rootpw --iscrypted $1$DNIhtN0D$8D.Ard1Aq48KP6NmtxZSx0
# SELinux configuration
selinux --disabled
# System timezone
timezone Europe/Paris
# Install OS instead of upgrade
install
# X Window System configuration information
xconfig --defaultdesktop=GNOME --depth=24 --resolution=1280x1024
# Disk partitioning information, fixed sizes, /data is what remains on disk
part /boot --bytes-per-inode=4096 --fstype="ext3" --size=200
part / --bytes-per-inode=4096 --fstype="ext3" --size=5000
part /var --bytes-per-inode=4096 --fstype="ext3" --size=5000
part /tmp --bytes-per-inode=4096 --fstype="ext3" --size=5000
part /usr --bytes-per-inode=4096 --fstype="ext3" --size=10000
part swap --bytes-per-inode=4096 --fstype="swap" --size=4000
part /data --bytes-per-inode=4096 --fstype="ext3" --grow --size=1

%packages
@base-x
@gnome-desktop
@base
@development-libs
@graphical-internet
@admin-tools
@development-tools
@kde-desktop
@printing
@sound-and-video
@legacy-software-development
@graphics
@office
@system-tools
@editors
@engineering-and-scientific

#--- Post-installation script
%post
#!/bin/bash
chroot /mnt/sysimage

echo "192.168.xxx.xxx netapp" >> /etc/hosts
echo "192.168.xxx.xxx nisserver" >> /etc/hosts

mkdir -p /netapp/vol3
mount 192.168.xxx.xxx:/vol/vol3 /netapp/vol3
cd /netapp/vol3/distros/rpms
#Installing NVIDIA kernel module, RPMs from internet.
rpm -ivh nvidia-graphics-helpers-0.0.26-27.el5.i386.rpm
rpm -ivh nvidia-graphics-devices-1.0-5.0.el5.noarch.rpm
rpm -ivh nvidia-graphics173.14.09-libs-173.14.09-99.el5.i386.rpm
rpm -ivh nvidia-graphics173.14.09-kmdl-2.6.18-53.el5PAE-173.14.09-99.el5.i686.rpm
rpm -ivh nvidia-graphics173.14.09-173.14.09-99.el5.i386.rpm

#Installing software (meaning doing links to autofs mount points)
ln -s /soft/abaqus/ /usr/local/abaqus
ln -s /soft/hyperworks8 /usr/local/hyworks
ln -s /soft/hyperworks7 /usr/local/hyworks7
ln -s /soft/msc /usr/local/msc
ln -s /soft/radioss /usr/local/radioss

#Copy nsswitch and other resolv.conf ....
cp -f /netapp/vol3/distros/post/nsswitch.conf /etc/nsswitch.conf

cd /root
umount /netapp/vol3



Have fun !

Nov 25, 2009

Howto install CVS/CVSNT server on RHEL/CentOS


First you'll have to check /etc/services for the definitions of the CVS used TCP ports :




grep -i cvs /etc/services
cvspserver 2401/tcp # CVS client/server operations
cvspserver 2401/udp # CVS client/server operations

Then you'll have to install either CVS package either CVSNT package :
yum install cvs
or
rpm -ivh cvsnt-2.5.04.3510-rh9-rpm.tar.gz

Now, set up users that will access the CVS server :
vim /etc/passwd
vim /etc/shadow

Then, setup a folder for the CVS data. I usually put this on an NFS share which is on a filer so that data is backuped and you have snapshots of it :
mkdir /home/cvsrepo
cvs -d /home/cvsrepo init
chgrp GID /home/cvsrepo (according to what you did in the /etc/passwd)
chmod g+w /home/cvsrepo

Now add the CVSROOT environement variable to all the users needed :

echo "export CVSROOT=/home/cvsrepo" >> /root/.bashrc
echo "export CVSROOT=/home/cvsrepo" >> /home/userXXX/.bashrc

Now time for setup the CVS server. It will be launched by Xinetd, so check you have it running on your system. It is running default on CentOS5, RHEL5, Suse, ...
/etc/init.d/xinetd status
It's Xinetd who will launch CVS each time a client is asking. This is configured in the /etc/xinetd.d folder; you'll have to add a file like this one :
cat /etc/xinetd.d/cvspserver
service cvspserver
{
disable = no
socket_type = stream
wait = no
user = root
group = systeme
log_type = FILE /var/log/cvspserver
protocol = tcp
env = '$HOME=/usr/local/cvspserver'
log_on_failure += USERID
port = 2401
server = /usr/bin/cvs
server_args = -f --allow-root=/home/cvsrepo pserver
}


Now restart you xinetd, and check you /var/log/messages that your new rule cvspserver has been loaded :
/etc/init.d/xinetd restart
cat /var/log/messages

Everything is now ok, your CVS server is up. Supposing you created a user named 'user1' on the cvs server named 'cvsserver' here is the CVSROOT you'll have to use either on UNIX systems, either on Windows with TortoiseCVS or another CVs client :
CVSROOT=:pserver:user1@cvsserver:/home/cvsrepo
For security reasons, it's possible to create CVS ONLY users. For that, go to the CVS folder and CVSROOT then. At this place there is a "CVS local passwd" alose named passwd. To add users able only to access the CVS and no the entire system, use htpasswd command or perl scripts :
htpasswd passwd user3

Have fun !

Nov 18, 2009

Playing with "find" and "dc"


First, here is how to find and print all files that were modified more than 300 days from now, and that are bigger than 30k. For all these files we print : User [tab] Size_in_kb [tab] Creation_date [tab] Access_date [tab] Path_to_the_file

find . -mtime +300 -size +30k -type f -printf "%u\t%k\t%TD\t%AD\t%p\n"
Now, another interesting thing could be knowing the total size of all these files. For that, print only the size, followed by "+p" and pipe it to dc :

find . -mtime +300 -size +30k -type f -printf "%k+p\n" | dc
At the end you'll have the total size of your files older than 300 days, and bigger than 30kb.

Multiple kill


Very simple but interesting, here is how to kill all the processes which "grep" a keyword :

ps aux | grep -i keyword | awk '{print $2}' | xargs kill -9

Aug 19, 2008

SCSI and SATA hotplug in Linux

Well, this is my first post of my first blog, I didn't really knew where to start from, so let's go on with some classic but useful stuff.
A lot of times I had to add a hard drive to a running linux server (or my personal box) without shutting it down; here is how i dit it on a lot of different versions of linux (starting with early 2.4 until today's testing 2.6.24). Check first if your hardware supports hotplug (SCSI proprietary drivers do generally support that and generic SATA linux driver AHCI supports also hotplug). For info about SATA and linux drivers, check out http://linuxmafia.com/faq/Hardware/sata.html.

First, plug your SCSI or SATA hard drive in the machine. You shouldn't see anything in your "dmesg".
Then, have a look at your /proc/scsi/scsi (use cat command, no text editor). It should look like :

Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
Vendor: SEAGATE Model: ST336607LC Rev: DS09
Type: Direct-Access ANSI SCSI revision: 03
Host: scsi0 Channel: 00 Id: 01 Lun: 00
Vendor: SEAGATE Model: ST3146807LC Rev: DS09
Type: Direct-Access ANSI SCSI revision: 03
Host: scsi0 Channel: 00 Id: 02 Lun: 00
Vendor: MAXTOR Model: ATLAS15K2_146SCA Rev: JNZ6
Type: Direct-Access ANSI SCSI revision: 03
Host: scsi0 Channel: 00 Id: 03 Lun: 00
Vendor: FUJITSU Model: MAX3147NC Rev: 5D03
Type: Direct-Access ANSI SCSI revision: 03
Host: scsi0 Channel: 00 Id: 04 Lun: 00
Vendor: MAXTOR Model: ATLAS15K2_146SCA Rev: JNZ6
Type: Direct-Access ANSI SCSI revision: 03
Host: scsi0 Channel: 00 Id: 06 Lun: 00
Vendor: SDR Model: GEM318P Rev: 1
Type: Processor ANSI SCSI revision: 02


This is obviously a list of all your up and running hdds (in this case a DELL PE1900 with SCSI backplane controller and 5 disks inside), including here the SCSI controller in 0060 position. As you may guess, what interests us is knowing the next free id for inserting our brand new disk.
Here the next and last free id is 5 on scsi0, channel0, lun0 (depending on your configuration, you may have several scsi controllers or several channels so be careful). In case you add several SCSI disks on a controller without rebooting the machine, the SCSI ids should match the physical position on the controller (else on reboot the kernel will remap the devices) or you should mount devices by UUID.
For SATA disks, don't use next free id, but next scsi. This is how /proc/scsi/scsi looks on my NForce4 with 4 SATA disks :

Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
Vendor: ATA Model: ST380211AS Rev: 3.AA
Type: Direct-Access ANSI SCSI revision: 05
Host: scsi1 Channel: 00 Id: 00 Lun: 00
Vendor: ATA Model: ST3808110AS Rev: 3.AA
Type: Direct-Access ANSI SCSI revision: 05
Host: scsi2 Channel: 00 Id: 00 Lun: 00
Vendor: ATA Model: WDC WD1600JS-00M Rev: 02.0
Type: Direct-Access ANSI SCSI revision: 05
Host: scsi3 Channel: 00 Id: 00 Lun: 00
Vendor: ATA Model: Hitachi HDT72503 Rev: V54O
Type: Direct-Access ANSI SCSI revision: 05

So now that we know what is the next free position for our device, we'll insert it into the system. For doing that, use following command, customized to your needs (this one is for the PE1900, the NForce4 runs only 4 SATAs) :
echo "scsi add-single-device 0 0 5 0" > /proc/scsi/scsiThis should hang out your system for a few seconds, and then your kernel should let you know that a drive has been added.
Further, you'll have to create new partitions. I use command line fdisk command (but QTParted, Gparted or parted work as well) :
fdisk /dev/sde, create new primary, etc.Then create the filesystems of your choice on the disk and mount them into your system.

P.S : The same command is used for removing hdds from the system :
echo "scsi remove-single-device 0 0 5 0" > /proc/scsi/scsiDo I have to mention that partitions on this hard have to be unmounted before doing that ?

Have fun !