Saturday, July 13, 2013

Apache Connection Establishment and serving requests

Apache server establishes a TCP connection with the client(browser) before serving requests.
Apache puts it's socket into LISTEN state using listen() system call.

TCP three-way handshake between client and server, can be briefed as follows:

1) Client end
    Client sends SYN
    Client moves into SYN SENT state

2) Server end
    Kernel hands SYN to Server
    Kernel sends SYN/ACK to the client
    Server moves to SYN RCVD state
    Connections in SYN RCVD state are added to SYN QUEUE(incomplete connection queue)

3) Client end 
   Client sends ACK

TCP Connection is ESTABLISHED. In the server end, once the ACK packet is received from the client, the connections in the SYN QUEUE(incomplete connection queue) are moved to the ACCEPT QUEUE. Apache will use the accept() system call to consume connections from the ACCEPT QUEUE.

Once the tcp connection is established between client and server, now the first http request data is passed from client to server

In the server end, the kernel passes connection into the server's accept() method.

The Kernel accepts up to /proc/sys/net/ipv4/tcp_max_syn_backlog (default 1024) requests to be in SYN_RCVD state(SYN QUEUE) - incomplete connections. Maximal number of remembered connection requests, which still did not receive an acknowledgement from connecting client. For each SYN requests received, it sends back SYN/ACK and awaits an ACK from the client. If the server, does not receive an ACK from the client, it retries sending SYN/ACK - /proc/sys/net/ipv4/tcp_synack_retries times (default 5 in linux), before dropping the connection. Once all the retries are failed, the client will get a RST packet from the server.

So at server end, we basically deal with two queues in Linux TCP implementation

  1. Incomplete connection queue(SYN QUEUE - Connections in SYN RCVD state)
  2. Accept Queue(Connections in ESTABLISHED state)
If the Accept Queue is full, then the kernel will impose a limit on the rate at which SYN packets are accepted. If too many SYN packets are received, some of them will be dropped.

It is the job of the application(Apache, in this case) to empty the Accept Queue(completed connection queue) by calling the accept() system call. 
Apache will accept() up to 'MaxClients' simultaneous client connections. The kernel will queue up to lower of either of the following - /proc/sys/net/core/somaxconn (default 128) or 'ListenBackLog' (default 511) -additional established connections. somaxconn is the Limit of socket listen() backlog. Going by the default values of  /proc/sys/net/core/somaxconn (default 128) and 'ListenBackLog' (default 511), the kernel shall queue upto 128 established connections since 128 is lower than 511. Above this limit, the kernel will drop additional SYN packets.

How to limit simultaneous connections per client?

Apache does not have an in-built mechanism to limit simultaneous connections per client. So by using tools such as iptables,it can be achieved.

Reference:
http://www.cyberciti.biz/files/linux-kernel/Documentation/networking/ip-sysctl.txt
http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html

Friday, July 5, 2013

Python script for checking if an IP address is valid

To know if an IP address is valid, here is a simple python script. Let us name the script as chkip.py

Pass the IP address to be validated as an argument for this program, like follows
python chkip.py  <IP Address>


#!/usr/bin/python
import re
import sys

def check_ip_validity(ipaddr):
    ValidIpAddressRegex = '^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
    ip_match = re.search(ValidIpAddressRegex,ipaddr)
    if ip_match:
       ip = 1
    else:
       ip = 0
    return ip

def main():
    ip = 0
    if check_ip_validity(sys.argv[1]):
       print "Valid IP"
    else:
       print "Not a valid IP"

if __name__ == '__main__':
    main()

NRPE and NSCA in Nagios

NRPE is used for performing active checks in Nagios
NSCA is used for performing passive checks in Nagios

check_nrpe (from NRPE) is used to initiate an active check from the  Nagios server. check_nrpe is called like a normal plugin by nagios server. check_nrpe initiated in the server, then contacts the nrpe daemon running on a  remote host(a host monitored by Nagios) and asks it to run a pre-configured check command and  returns the results to nagios server.

NSCA is used when a passive check is initiated from a remote host(a host monitored by Nagios server). In the remote host, a  wrapper script for checking a service, is called by cron or some other method,  which in turn  passes the results to the send_nsca  program running in the same remote host. send_nsca contacts the nsca daemon on the nagios server. nsca daemon passes the results of the check to nagios.