Tag Archive : linux

/ linux

In computer science especially in Unix world, a shell is a software that provides an interface for users to access kernel services. The name shell originates from shells being an outer layer of interface between user and the internals of operating system (kernel). Some shell we might know are: bash, csh, tcsh, sh, etc.

In this article, I will show you how to build a simple shell. Our shell can execute command which is inputted by user. But before that, we will cover some basic knowledge about how things going on.

How can our shell execute a command? The answer lies on the capability of exec() function family. Exec will execute command given by them and passing arguments if any. As I said exec() family functions, the actual function we can use are: execl(), execlp(), execle(), execv(), execvp().

How to distinguish between these function?

The suffix ‘l’ (el) means exec commands expect a null-terminated list (hence the “l” for list) of arguments, so to execute “/bin/ls/ -l /” we will call

execl("/bin/ls", "-l" , "/" , (char*) 0);

The suffix ‘v’ (vi) means exec commands expect an array or vector (hence the “v” for vector) of arguments. Here is the snippet for doing same thing as previous:

char *vec[4];

vec[0]="ls";
vec[1]="-l";
vec[2]="/";
vec[3]=(char *)0;
execv("/bin/ls", vec);

The suffix ‘e’ take an additional argument which is an array of char containing the environment (hence the ‘e’ for environment) to be passed to the exec-ed command. Both le and and ve expect an array.

The suffix ‘p’ search the PATH for the command named in their first argument. The one without p don’t.

To use them we should include <unistd.h> header.

In this article we will use execvp() to execute our command.

Now to do exec() thing, we will need help from fork(). What is fork? In computer science, a process do fork will creates a copy of itself. Under Unix OS, the parent and the child process can tell each other apart by examining the return value of the fork() system call. In the child process, the return value of fork() is 0 while the parent side has PID of newly created child process as return value.

Why we should create a fork? First, when exec has finish executing command, it would be exited by default. Our shell must remain running even after the command finished unless we are ordered to exit. Second, having ability to “background”-ing a process executed. You would noticed that when we enter a command in shell like bash and end it with &, our newly executed command would run independently while the shell itself is ready to receive new command.

Here is the complete source code for our shell:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

const int BUFFER_SIZE = 1<<16;
const int ARR_SIZE = 1 << 16;
/* parse arguments and creating a vector of argument */
void parse_args(char* buffer, char** args, size_t args_size, size_t *nargs);

/* SIGNAL HANDLER */
/* handler for SIGCHLD */
void child_handler(int);

/* handler for SIGINT */
void interrupt_handler(int);

int child_count = 0;

int main(int argc, char* argv[]) {
   char buffer[BUFFER_SIZE];
   char* args[ARR_SIZE];
   int ret_status;
   size_t nargs;
   pid_t pid;
   int background;
   signal(SIGCHLD, &child_handler);
   signal(SIGINT, &interrupt_handler);
   while(1) {
      background = 0;
      printf("$> ");
      fgets(buffer, BUFFER_SIZE, stdin);
      parse_args(buffer, args, ARR_SIZE, &nargs);
      if(nargs==0) continue;
      if(!strcmp(args[0],"exit")) {
         printf("Session terminated\n");
         exit(0);
      }
      if( !strcmp(args[nargs-1], "&") ) {
         background = 1;
         args[nargs-1] = NULL;
         nargs--;
      }
      child_count += 1;
      pid = fork();
      if(pid > 0) {
      /* PARENT */
      if( !background ) {
         pid = wait(&ret_status);
         printf("Child (%d) finished\n", pid);
      } else {
         printf("[ ] %d\n", pid);
      }
   } else if(pid == 0) {
      /* CHILD */
      if( execvp(args[0], args) ) {
         puts(strerror(errno));
         exit(127);
      }
   } else {
      printf("Error: Can not fork\n");
      exit(1);
      }
   }
   return 0;
}

void parse_args(char* buffer, char** args, size_t args_size, size_t *nargs) {
   if( strlen(buffer) > 0 ) {
      char *buf_args[args_size];
      char **cp;
      char *wbuf;
      size_t i,j;
      wbuf=buffer;
      buf_args[0] = buffer;
      args[0] = buffer;
      for(cp=buf_args; (*cp=strsep(&wbuf," \n\t")) != NULL;) {
         if((*cp != '\0') && (++cp >= &buf_args[args_size]))
         break;
      }
      for(j=i=0; buf_args[i] != NULL; i++) {
         if(strlen(buf_args[i]) > 0)
         args[j++]=buf_args[i];
      }
      *nargs=j;
      args[j]=NULL;
   } else {
      *nargs = 0;
   }
}

/* handler for SIGCHLD */
void child_handler(int sig_type) {
   int child_status;
   pid_t child;
   /* Getting exit status from child */
   child = waitpid(0, &child_status, 0);
}

/* handler for SIGINT */
void interrupt_handler(int sig_type) {
   printf("\n%d child(s) has been spawned successfully. Session terminated\n", child_count);
   exit(0);
}

Any comment or question is welcomed.

Add New System Call to Linux 3.6.1

November 24, 2015 | Article | No Comments

As promised, this time I will show you how to add new syscall to linux 3.6.1.

Please note that the overall kernel structure in linux prior to 3.2 is different to the newer one so adding syscall in 3.6.1 would has different technique than technique discussed earlier. But by the way, the step for adding system call is similiar to previous article (step by step compile kernel 3.6.1)

If you haven’t download linux 3.6.1 you can download it from http://kernel.org/ website.

wget http://www.kernel.org/pub/linux/kernel/v3.x/linux-3.6.1.tar.xz

The reason I used linux-3.6.1.tar.xz instead of linux-3.6.1.tar.gz or linux-3.6.1.tar.bz2 is simply because of size.

Make sure you move the source to /usr/src/ directory. Do that using root access.

Now extract the source code.

tar -Jxf linux-3.6.1.tar.xz<br>cd linux-3.6.1

We can take the old configuration as our basis for creating configuration file.

cp /boot/config-2.6.35.22-generic .config

In this case I use kernel 2.6.35.22-generic. It can be different in your system so match the version number with your current kernel version.

It’s a wise way to see what we can do by invoking make. A little help could give us hint

make help

Now, to configure the config file, invoke

make menuconfig

After deciding what configuration you choose, It’s time for compilation. We will using generic way of compilation. It is the standard way provided by kernel and not platform oriented.

Now let’s jump into main subject. We will modify some files and do it sequentially and in the last we will test our new syscalls.

I’m going to create 3 syscalls, same as previous article: generate odd random-number, generate even random-number, and a dummy syscall which add input integer with 10.

Open and edit file /usr/src/linux-3.6.1/arch/x86/syscall/syscall_32.tbl. At end of file add 3 entries:

  • 350 i386 oddrandom sys_oddrandom
  • 351 i386 evenrandom sys_evenrandom
  • 352 i386 mycall sys_mycall

Did you notice number above? The entries are registered with unique numbers as seen above. Our 3 syscalls have id 350, 351, and 352. It’s easy to figure it out :). You can add more or less than this example, just remember what number your syscalls are.

Open and edit file /usr/src/linux-3.6.1/include/linux/syscalls.h. Add following entries before #endif:

  • asmlinkage unsigned int sys_oddrandom();
  • asmlinkage unsigned int sys_evenrandom();
  • asmlinkage int sys_mycall(int i);

Now create a new folder in /usr/src/linux-3.6.1/kernel, named randomsys/.

Create 4 files: sys_oddrandom.c; sys_evenrandom.c; sys_mycall.c; Makefile

Open and edit file “/usr/src/linux-3.6.1/kernel/randomsys/sys_oddrandom.c” with:

#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/random.h>

asmlinkage unsigned int sys_oddrandom()
{
   unsigned int v = 0;
   while( (v=get_random_int()) % 2 != 1 );
   return v;
}

Open and edit file “/usr/src/linux-3.6.1/kernel/randomsys/sys_evenrandom.c” with:

#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/random.h>

asmlinkage unsigned int sys_evenrandom()
{
   unsigned int v = 0;

   while( (v=get_random_int()) % 2 != 0 );

   return v;
}

Open and edit file “/usr/src/linux-3.6.1/kernel/randomsys/sys_mycall.c” with:

#include <linux/kernel.h>
#include <linux/syscalls.h>

asmlinkage int sys_mycall(int i) {
    return i+10;
}

Now open and edit “/usr/src/linux-3.6.1/kernel/randomsys/Makefile” with:

obj-y    := sys_oddrandom.o
obj-y    += sys_evenrandom.o
obj-y    += sys_mycall.o

Now open and edit “/usr/src/linux-3.6.1/kernel/Makefile“. Locate line with obj-y += power/. In my case it is on line 26th. Now add new entry below it.

obj-y += randomsys/

Next, compile our kernel and its modules. Invoke this command:

make

The process could be 1 to 4 hours depending on your system performance. For old machine like mine, it could be around 4 hours to do so. In this step the compiled kernel is stored in binary form as arc/x86/boot/bzImage file. Based on kernel headers it will compile the kernel modules (device driver, filesystem, network, etc) and generate .ko files which are kernel objects. These modules also called Loadable Kernel Modules (LKM).

Next, we will install kernel modules. to do so we can invoke

make modules_install

This step will copy all kernel modules (*.ko) to /lib/modules/<version>/kernel/ folder.

Next we will install the kernel itself. We did that by invoking

make install

This step copy the arch/x86/boot/bzImage to /boot folder and copy the .config to /boot/config-<latest version> and generate System.map file.

Next we need to create initramfs file. Next time I would write article about initramfs, but for this time just do so.

update-initramfs -c -k <version>

Here <version> can be 3.2.29 for this case.

Next we have to update the boot loader. I’m using GRUB so we have to invoke:

update-grub

This command automatically probe the kernels in /boot folder and add the entries in configuration file, grub.cfg

Restart the system and look at your bootloader entry. choose the new kernel in bootloader. Now open terminal and invoke

uname -r

Congratulations, you have build new kernel with our own syscalls now! Let’s test now.

Create 2 file: testmycall.h and testmycall.c. You can place it anywhere you want.

Now, open and edit testmycall.h

#include <linux/unistd.h>

unsigned int oddrandom() {
   return syscall(350);
}
unsigned int evenrandom() {
   return syscall(351);
}
unsigned int mycall(int i) {
   return syscall(352,i);
}

You must have known what those numbers are, aren’t you? 🙂

Now open and edit testmycall.c

#include <linux/unistd.h>
#include <sys/syscall.h>
#include "testmycall.h"

int main() {
   unsigned int v1=0,v2=0;
   int keluar=0;

   v1 = oddrandom();
   v2 = evenrandom();
   keluar = mycall(10);

   printf("v1         = %u\n",v1);
   printf("v2         = %u\n",v2);
   printf("keluar     = %d\n",keluar);

   return 0;
}

Compile and see the result by yourself 🙂

Add New System Call to Linux 3.2

November 24, 2015 | Article | 1 Comment

What is syscall? Syscall is abbreviation from system call, a service provided by kernel to user program who request for it. It may include hardware related services such as hard disk access, creating and executing new process, also communicationg with integral kernel services (like scheduling). System calls is essential interface between a process and the operating system.

At several past article, we have discussed how to compile a new kernel (based on version 3.6.1). This time, we will try to add some kernel syscall. Our own syscall precisely. And yes, this is part of my course homework. Let’s get start to our subject.

For this time why do we use Linux 3.2.29 version? Well it’s part of the homework though. But next time maybe I will write another article of writing syscall for Linux 3.6.1. Please note that the overall kernel structure in linux prior to 3.2 is different to the newer one so adding syscall in 3.6.1 would has different technique than technique discussed here. But by the way, the step for adding system call is similar to previous article (step by step compile kernel 3.6.1)

Now download the kernel we need at http://kernel.org/ website. In this case we need 3.2.29.

wget http://www.kernel.org/pub/linux/kernel/v3.x/linux-3.2.29.tar.xz

The reason I used linux-3.2.29.tar.xz instead of linux-3.2.29.tar.gz or linux-3.2.29.tar.bz2 is simply because of size.

Make sure you move the source to /usr/src/ directory. Do that using root access.

Now extract the source code.

tar -Jxf linux-3.2.29.tar.xz
cd linux-3.2.29

We can take the old configuration as our basis for creating configuration file.

cp /boot/config-2.6.35.22-generic .config

In this case I use kernel 2.6.35.22-generic. It can be different in your system so match the version number with your current kernel version.

It’s a wise way to see what we can do by invoking make. A little help could give us hint.

make help

Now, to configure the config file, invoke

make menuconfig

After deciding what configuration you choose, It’s time for compilation. We will using generic way of compilation. It is the standard way provided by kernel and not platform oriented.

Now it’s time to get to our main subject. We will modify some files and do it sequentially and in the last we will test our new syscalls.

I’m going to create 3 syscalls: generate odd random-number, generate even random-number, and a dummy syscall which add input integer with 10.

Now create a new folder in kernel root directory, in this case /usr/src/linux-3.2.29, named randomsys/.

Open and edit file /usr/src/linux-3.2.29/arch/x86/kernel/syscall_table.S. At end of file add 3 entries:

  • .long sys_oddrandom
  • .long sys_evenrandom
  • .long sys_mycall

See number above? The entries is registered with unique numbers as seen above. Our 3 syscalls have id 349, 350, and 351. It’s easy to figure it out :). You can add more or less than this example, just remember what number your syscalls are.

Open and edit file /usr/src/linux-3.2.29/arch/x86/include/asm/unistd_32.h. Locate line with text:

#ifdef __KERNEL__
#define NR_syscalls 349

You see some number on NR_syscalls, right? In this case is 349. Now look upward and then you will see some entries with __NR_ suffix. We will add some entries like those too. Add these entries after the latest entry:

  • #define __NR_oddrandom 349
  • #define __NR_evenrandom 350
  • #define __NR_mycall 351

Now you would be figure out what those numbers are. Yep, that are our unique number we add on syscall_table.S file. Then change number on NR_syscalls with 352.

Next we will open and edit /usr/src/linux-3.2.29/include/linux/syscalls.h. Add following entries before #endif:

  • asmlinkage unsigned int sys_oddrandom();
  • asmlinkage unsigned int sys_evenrandom();
  • asmlinkage int sys_mycall(int i);

Now open and edit /usr/src/linux-3.2.29/Makefile. Locate entries with:

core-y        += kernel/ mm/ fs/ ipc/ security/ crypto/ block/

Add randomsys/ to end of that line. Here randomsys/ is our newly created folder. If you did correctly your entry would be:

core-y        += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ randomsys/

Now create 3 files in directory /usr/src/linux-3.2.29/randomsys/. Those are sys_oddrandom.c; sys_evenrandom.c; sys_mycall.c.

Now open and edit /usr/src/linux-3.2.29/randomsys/sys_oddrandom.c

#include <linux/linkage.h>
#include <linux/kernel.h>
#include <linux/random.h>

asmlinkage unsigned int sys_oddrandom() {
   unsigned int v = 0;
   while( (v=get_random_int()) % 2 != 1 );
   return v;
}

Now open and edit /usr/src/linux-3.2.29/randomsys/sys_evenrandom.c

#include <linux/linkage.h>
#include <linux/kernel.h>
#include <linux/random.h>

asmlinkage unsigned int sys_evenrandom() {
   unsigned int v = 0;
   while( (v=get_random_int()) % 2 != 0 );
   return v;
}

Now open and edit /usr/src/linux-3.2.29/randomsys/sys_mycall.c

#include <linux/linkage.h>
#include <linux/kernel.h>

asmlinkage int sys_mycall(int i) {
   return i+10;
}

Now create and edit file /usr/src/linux-3.2.29/randomsys/Makefile

obj-y    := sys_oddrandom.o
obj-y    += sys_evenrandom.o
obj-y    += sys_mycall.o

Next, compile our kernel and its modules. Invoke this command:

make

The process could be 1 to 4 hours depending on your system performance. For old machine like mine, it could be around 4 hours to do so. In this step the compiled kernel is stored in binary form as arc/x86/boot/bzImage file. Based on kernel headers it will compile the kernel modules (device driver, filesystem, network, etc) and generate .ko files which are kernel objects. These modules also called Loadable Kernel Modules (LKM).

Next, we will install kernel modules. to do so we can invoke

make modules_install

This step will copy all kernel modules (*.ko) to /lib/modules/<version>/kernel/ folder.

Next we will install the kernel itself. We did that by invoking

make install

This step copy the arch/x86/boot/bzImage to /boot folder and copy the .config to /boot/config-<latest version> and generate System.map file.

Next we need to create initramfs file. Next time I would write article about initramfs, but for this time just do so.

update-initramfs -c -k <version>

Here <version> can be 3.2.29 for this case.

Next we have to update the boot loader. I’m using GRUB so we have to invoke:

update-grub

This command automatically probe the kernels in /boot folder and add the entries in configuration file, grub.cfg

Restart the system and look at your bootloader entry. choose the new kernel in bootloader. Now open terminal and invoke

uname -r

Congratulations, you have build new kernel with our own syscalls now! Let’s test now.

Create 2 file: testmycall.h and testmycall.c. You can place it anywhere you want.

Now, open and edit testmycall.h

#include <linux/unistd.h>

#define __NR_oddrandom 349
#define __NR_evenrandom 350
#define __NR_mycall 351

unsigned int oddrandom() {
   return syscall(__NR_oddrandom);
}
unsigned int evenrandom() {
   return syscall(__NR_evenrandom);
}
unsigned int mycall(int i) {
   return syscall(__NR_mycall,i);
}

You must have known what those numbers are, aren’t you? 🙂

Now open and edit testmycall.c

#include <linux/unistd.h>
#include <sys/syscall.h>
#include "testmycall.h"

int main() {
   unsigned int v1=0,v2=0;
   int keluar=0;

   v1 = oddrandom();
   v2 = evenrandom();
   keluar = mycall(10);

   printf("v1         = %u\n",v1);
   printf("v2         = %u\n",v2);
   printf("keluar     = %d\n",keluar);

   return 0;
}

Compile and see the result by yourself 🙂

What is Initial Ramdisk?

November 24, 2015 | Article | 2 Comments

Initial ramdisk is a scheme for loading a temporary filesystem into memory in the boot process of the Linux kernel. You could say it is a pseudo filesystem reflect / mirror to system. There are two scheme, initrd and initramfs. They are refer to slightly different methods and commonly used to make preparations before the real root filesystem can be mounted.

Many Linux distributions ship a single generic kernel image. They do that as they expect a wide variation of user’s hardware that might be met and thus the kernel need to be as flexible as possible. Therefore, developers need to avoid to hardcoded handling for so many special cases into the kernel body but still have to handle thus cases. The initial boot stage with a temporary root filesystem is used. This root filesystem can contain user-space halpers which do the hardware detection, module loading, and device discovery necessary to get the real root filesystem mounted.

As said before, initial ramdisk is an image of initial root filesystem (along with the kernel image), it must be stored somewhere accessible by the Linux bootloader or the boot firmware.

Prior to linux version 2.6.12, Linux use initrd scheme. The image may be a filesystem image (optionally compressed) which is made available in a special block device (/dev/ram) that is then mounted as the initial root filesystem. Once the initial root filesystem is up, the kernel executes /linuxrc as its first process. When it exits, the kernel assumes that the real root file system has been mounted and executes “/sbin/init” to begin normal user-space boot process.

In initramfs (Linux 2.6.13 onward) scheme, the image may be a cpio archive (optionally compressed). The archive is unpacked by the kernel into a special instance of a tmpfs that becomes the initial root filesystem. With this scheme, there is no requirement of intermediate filesystem or block drivers to be compiled into kernel.

Compiling Linux Kernel, Step by Step

November 24, 2015 | Article | 4 Comments

— This is old article I wrote on my old Nest —

Recently I was doing some linux kernel compilation for a course homework. I did it manually. Someone said it’s so complicated so I will share my guide for linux kernel compilation. Here I use the most recent kernel version as October 9th, 2012. The version is 3.6.1. All operations are performed on Ubuntu distribution.

Check for your current linux kernel version. You can do it by typing this on your terminal.

uname -r

or

cat /proc/version

Now download the latest kernel at http://kernel.org/ website. In this tutorial we would use kernel version 3.6.1.

wget http://www.kernel.org/pub/linux/kernel/v3.x/linux-3.6.1.tar.xz

The reason I used linux-3.6.1.tar.xz instead of linux-3.6.1.tar.gz or linux-3.6.1.tar.bz2 is simply because of download size.We will following a convention or common practice of kernel building so we will use /usr/src directory. Make sure you move the source to /usr/src/ directory. Do that using root access.

Now extract the source code.

tar -Jxf linux-3.6.1.tar.xz
cd linux-3.6.1

In linux-3.6.1 folder there would be some files and folders. Some of them used as special purpose as:

arch – describe all architecture support by kernel
crypto – contain cryptographic implementation like AES, DES
drivers – all drivers modules (ID, SCSI, Ethernet device, Wireless)
fs – all filesystem implementation (ext4, FAT, NTFS)
net – all network protocol implementation (IPv4, IPv6, tcp, 802.11)

Now let’s configure our kernel source. The kernel compilation need a configuration file that contain lots of variable to help to understand what modules we need to compile. Specific kernel variable can be found at kernel.org

We can take the old configuration as our basis for creating configuration file.

cp /boot/config-2.6.35.22-generic .config

Note that I use kernel 2.6.35.22-generic so I copy the configuration file. It can be different in your system so match the version number with your current kernel version.

It’s a wise way to see what we can do by invoking make. A little help could give us hint.

make help

Now, to configure the config file, invoke

make menuconfig

After deciding what configuration you choose, It’s time for compilation. We will using generic way of compilation. It is the standard way provided by kernel and not platform oriented.

To compile the kernel and its modules we can invoke:

make

The process could be 1 to 4 hours depending on your system performance. For old machine like mine, it could be around 4 hours to do so. In this step the compiled kernel is stored in binary form as arc/x86/boot/bzImage file. Based on kernel headers it will compile the kernel modules (device driver, filesystem, network, etc) and generate .ko files which are kernel objects. These modules also called Loadable Kernel Modules (LKM).

Next, we will install kernel modules. to do so we can invoke.

make modules_install

This step will copy all kernel modules (*.ko) to /lib/modules/<version>/kernel/ folder.

Next we will install the kernel itself. We did that by invoking.

make install

This step copy the arch/x86/boot/bzImage to /boot folder and copy the .config to /boot/config-<latest version> and generate System.map file.

Next we need to create initramfs file. What is iniramfs? You can find out here.

update-initramfs -c -k <version>

Here <version> can be 3.6.1 for this case.

Next we have to update the boot loader. I’m using GRUB so we have to invoke:

update-grub

This command automatically probe the kernels in /boot folder and add the entries in configuration file, grub.cfg

Restart the system and look at your bootloader entry. choose the new kernel in bootloader. Now open terminal and invoke.

uname -r

The kernel version should be 3.6.1 now.

IPTables Configuration Tutorial

November 24, 2015 | Article | No Comments

This article will discuss about linux firewall configuration traditionally (using iptables). If you are searching for newer interface such as UFW and FirewallD, this is not the case.

What is iptables?

IPTables is a user space application program that allows a system administrator to configure tables provided by the Linux Kernel Firewall (implemented as different Netfilter modules) and the chains and rules it stores or simply it used to manage firewall rules. To put it general, iptables is used for configuring the packets flow in the network, rules out what packets can be received, transmitted, or forwarded to or from IPs listed in the tables.

This article will give basic instruction of how iptables work and structured. We will also understanding rules for network management. Later, we might expected reading and writing iptables firewall rules will be easy.

Iptables is installed by default on every linux machine. However if you found no iptables, you can install it.

# Debian-based (Debian, Ubuntu, etc)
apt-get install iptables

# RPM-based (RHEL, Centos, etc)
yum install iptables

# Arch-based (Arch Linux, etc)
pacman -S iptables

# Zypper-based (Opensuse, etc)
zypper install iptables

It’s important to note that iptables operated on Linux Kernel Firewall, so we need root privilege.

Let’s start by executing this command on your linux terminal:

iptables --help

Those command will give summary of what iptables program can do.

On a high-level, iptables might contain multiple tables. Tables might contain multiple chains. It can be built-in or user-defined. Chains might contain multiple rules. Rules are defined for packets and will determine what fate will the packets got.

Summary, the structure will be: iptables -> tables -> chains -> rules.

By default, iptables has 4 built-in tables: filter table, nat table, mangle table, raw table.

1. Filter Table

Default for iptables. If another table is not defined, we will use filter table. The built in chains for filter table are:

  • INPUT chain – incoming packet to firewall. It is the chain for packet coming to local server
  • OUTPUT chain – outgoing from firewall. It is chain generated locally and going out of the local server
  • FORWARD chain – packet for another NIC (Network Interface Card) on the local server. It is chain for packet routed through the local server.

2. NAT table

This is iptable for NAT (Network Address Translation). It has following built-in chains:

  • PREROUTING chain – alter packets before routing. Packet translation happens immediately after the packet comes to the system (and before routing). This helps to translate the destination ip address of the packets to something that matches the routing on the local server. This is used for DNAT (Destination NAT)
  • POSTROUTING chain – alter packets after routing. Packet translation happens when the packets are leaving the system. This helps to translate the source ip address of the packets to something that might match the routing on the destination server. This is used for SNAT (Source NAT).
  • OUTPUT chain – NAT for locally generated packets on the firewall.

3. Mangle table

Table for specialized packet alteration. This table alters QoS bits in the TCP header. Mangle table has the following built-in chains:

  • PREROUTING chain
  • OUTPUT chain
  • FORWARD chain
  • INPUT chain
  • POSTROUTING chain

4. Raw table

This table is for configuration excemptions. This table has following built-in chains:

  • PREROUTING chain
  • OUTPUT chain

The Rules

Rules are the core of firewall. They are the law for your firewall to inspect packets and determine what it will do to them. Giving wrong instruction to firewall (giving wrong rules) will make you end in some uncomfortable situation. For example: it will drive your friends away or even can’t distinguish who are friends and who are enemy. Same with your firewall.

Now let’s see the basic of iptables rules.

  • Rules contain a criteria and a target
  • If the criteria matched, it goes to the rules specified in the target (or) executes the special values mention in the target
  • If the criteria is not matched, it will moves on to the next rule and sequentially see rules until it found matched criteria or nothing at all

The value of possible action executed under the matched condition can be summarized to following values:

  • ACCEPT – The packet will be accepted by firewall
  • DROP – The packet will be discarded
  • REJECT – Similar to DROP but firewall will give inform the sender for packet rejection
  • QUEUE – The packet will be passed to userspace
  • RETURN – The firewall will stop executing the next set of rules in the current chain for this packet and the control will be returned to the calling chain.

For every chains there would be columns like target, prot, opt, source, destination.

  • Target is value or action took when the condition met. We have discuss above.
  • Prot or protocol inform us what protocol used. It can be TCP, UDP, ICMP, etc
  • Opt or special options for the specific rule.
  • Source is source ip-addres of packet.
  • Destination is destination ip-address of packet.

Basic IPTables Command

Now, let’s discuss about command used to manipulating rules. The command will be in bold form, while explanation will be next to it.

-A : append
This command append / add rule at the end of list / table.
example :
iptables -A INPUT : append to INPUT chains on FILTER table.

-D : delete
This command delete one rule pointed by a single number which indicated row. The row number is called index. We have to specify the rule that want to be deleted by specifying row number / index where the rule resided.
example :
iptables –D INPUT 1 : delete first entry on INPUT chain

-R : replace
It replace rule with new rule. The old rule will be overwritten and occupied by new one. The order of overall tables is still same.
example :
iptables –R INPUT 2 –s 192.168.1.3 –j DROP : replace rules on entry number 2

-I : insert
Inserting new rule in the table. When we use insert, our new rule will be place on that index while the rest of index will be moved to next sequence. Simply we can say when we insert a rule to row 1, the old rule will be on row 2 later. And so on.
example :
iptables –I INPUT 3 –s 192.168.1.3 –j ACCEPT : insert rule at entry number 3

-L : list
This command will list every rule we have created.
example :
iptables –t nat –L : list all rules on chain in table nat
iptables –L : list all rules on chain in all tables

-F : flush
This command will flush / delete every rule on a table.
example :
iptables –F OUTPUT : flush the content of OUTPUT

-N : new-chain
This command will create a new chain (table) with a name specified in the argument.
example :
iptables –N cha-IN : create new chain in table filter with name cha-IN

-X : delete-chain
This command will delete chain. The deletable chain is the chain which created by -N command. In order the command executed successfully, the chain must be empty or no rules exists.
example :
iptables –x cha-IN : remove chain cha-IN

-P : policy
This command create a default policy to a chain. When a packet which is not suitable with other rules occured, the default policy will determined what machine will do.
example :
iptables –P INPUT DROP : set default policy that drop packet for every unhandled packet on chain INPUT

E : rename-chain
This command will rename a chain. The renamable chain is the chain which created using -N command.
example :
iptables –E eth0_IN cha-IN : rename eth0_IN to cha-IN

-h : help
print out help for iptables.

IPTables Parameters

Iptables receive parameters. In this section we will discuss what is the function of parameter you find when you type `iptables –help` last time.

-p : protocol

Used for checking protocol type. Common protocols are TCP, UDP, ICMP, and ALL. You can read list of protocol available at /etc/protocols. Whenever we used ! we say as “not”. For example we want every protocol can over our network except ICMP. It means not ICMP.
Contoh :
iptables -A INPUT -p ! icmp : allow packet which is not icmp
iptables -A INPUT -p tcp : allow packet which is tcp

-s : source ip-address

Used for matching packet by source ip-address. The address specified here can be single node address such as 192.168.1.1 or a network by netmaskin such as 192.168.1.0/255.255.255.0 or also can be written as 192.168.1.0/24.
example :
iptables -A INPUT -s 192.168.1.3

-d : destination
Used for matching packet by destination address. The usage is similiar to –s
example :
iptables -A OUTPUT -d 192.168.1.3

-j : jump
Used to take values or action for matched packet.
example :
iptables -A INPUT -j DROP

-i : in-interface
Used for matching by incoming interface. This matching is only applied to chain INPUT, FORWARD
example :
iptables -A INPUT -i eth0

-o : out-interface
Used for matching by ougoing interface. The usage is similiar to. Only applied to chain OUTPUT, FORWARD
example :
iptables -A OUTPUT -o eth1

MORE ON IPTABLES TARGET

Target or jump is what action we give to certain packet.

ACCEPT every packet will be received by firewall and forwarded to destination of packet.
example :
iptables -A INPUT -p tcp -–dport 80 -j ACCEPT

DROP
Drop or throw every packet without warning to sender IP address.
example :
iptables -A INPUT -p tcp -–dport 80 -j DROP

REJECT
Reject received packet but will fives signal to sender IP address.
example :
iptables -A INPUT -p tcp -–dport 80 -j REJECT

RETURN
Reject every packet but firewall will gives ICMP error to packet sender. The default would be port-unreachable message. Message can be changed such as icmp-net-unreachable, icmp-host-unreachable, icmp-proto-unreachable, icmp-net-prohibited, etc
example :
iptables -A INPUT -p tcp -–dport 80 -j REJECT –reject-with icmp-net-unreachable

LOG
There are some option used accompanying this target. First is to determining log level. Common log level used are debug, info, notice, warning, err, crit, alert and emerg. Second is -j LOG –log-prefix which used to give string on prefix log so the log reading can be easy.
example :
iptables -A FORWARD -p tcp -j LOG -g-level debug
iptables -A INPUT -p tcp -j LOG -log-prefix “INPUT Packets”

SNAT
Used for Source Network Address Translation. The target is applied for NAT table at chain POSTROUTING. If first packet of connection is applied to SNAT, the the next packet on that connection would have same condition.
example :
iptables –t nat –A POSTROUTING –o eth0 –j SNAT –to-source 194.236.50.155-194.236.50.160:1024-32000

DNAT
Opposite of SNAT, DNAT used for Destination Network Address Translation at packets header. DNAT Only applied to table NAT chain PREROUTING AND OUTPUT or user define chain called by those two.
example :
iptables –t nat –A PREROUTING –p tcp –d 15.45.23.67 –dport 80 –j DNAT –to-destination 192.168.0.2

MASQUERADE
Work similiar with SNAT but this target doesn’t need option -to-source. MASQUERADE is designed to work on non-permanent connection like dial-up or DHCP that has dynamic IP allocation.
Like SNAT, the target work on table NAT on chain POSTROUTING.
example :
iptables –t nat –A POSTROUTING –o eth0 -dport 80 –j MASQUERADE

REDIRECT
REDIRECT used for redirecting route to machine. This target is used to redirect a packet that over some port through proxy application. Moreover it is used for establishing transparent proxy mechanism. For example we want to redirect all connection for http port so it will entering http proxy application such as Squid. This target is only applied for PREROUTING and OUTPUT chain on table NAT or user defined chain used by those chains.
example :
iptables -t nat -A PREROUTING -i eth1 -p tcp –dport 80 -j REDIRECT –to-port 3128
iptables -t nat -A PREROUTING -p tcp -d 0/0 –dport 80 -j REDIRECT –to-port 8080

Social media & sharing icons powered by UltimatelySocial