Sunday, June 29, 2014

PaaS: Google AppEngine v.s. Heroku

Reference

Intro

I am putting "Reference" section as the first section in this post because that I am writing this post totally based on the refereces.

Comparison

Language Support

Google AppEngine: Python, Java, PHP, Go / Cloud SQL(MySQL compatible)
Heroku: Ruby, Java, Node.js, Python, PHP, Clojure, Scala / PostgreSQL, MongoDB, Cloudant, Redis

Comments for Google AppEngine

AppEngine’s proprietary, read-only nature results in tedious and unnecessary code refactoring; apps have to be written specifically with AppEngine in mind, API’s have to be written specifically for AppEngine, even standard Java code has to be extensively altered to fit into the AppEngine environment.

Google insists on AppEngine customers only using its BigTable non-relational database, although they have also recently added some support for CloudSQL.

Comments for Heroku

Heroku’s database-platform choices reflect a collection that is in widespread use already in the wider world.

Comments on Both

Heroku’s database-platform choices reflect a collection that is in widespread use already in the wider world.


My Summary

I only have a little developing experience on both PaaS platforms. However, from the referece I found, more people suggest Heroku than Google AppEngine. It's because that Google AppEngine is tie-in, lack of flexibility, and hard to move to regular VPS if needed.

IaaS, PaaS, SaaS

Intro

To start a new web-based project (mainly HTTP/HTTPS-related things), we do have multiple choices for the platform. We can host a whole virtual machine, like AWS or Linode. Or, we can host put our code on Google Appengine or Heroku. They all have different pros and cons, and we should pick the one which matches the purpose of the project.

SaaS: Software as a Service

Examples

  • Gmail
  • Google+

PaaS: Platform as a Service

One can develop applications and let them execute on top of the platform which take care of the execution.

Vendors manage:

  • runtime
  • middleware
  • O/S
  • virtualizatoin
  • server
  • storage
  • networking

Users manage:

  • application
  • data

Examples

  • Heroku
  • Google App Engine

IaaS: Infrastructure as a Service

Users buy fully outsource service (the whole virtual machine)

Examples

  • AWS(Amazon Web Services)
  • Linode

Reference

Friday, June 13, 2014

SYN Flood DDOS Defense in Kernel Code

Environment

Kernel 2.6.32

Knowledge

SYN Flood DDOS is still a big headache for system administrators, and we don't really have a solution for this kind of attack so far in the real world.
To start a connection between a server and a client, they have to perform "TCP 3-Way Handshake" first without any failure:
  1. client -> server: SYN
  2. server -> client: SYN-ACK
  3. client -> server: ACK
* SYN/ACK are signal bits in TCP packages.
However, not everyone in the internet is friendly and follow every rule we have. An attacker may only send SYN-package (first step in the 3-Way Handshake) but with pretty large amount, the server then may run out of resource since there are too many half-open connections. And, the attacker can even apply random IP source in the packages so that the server is not able to distinguish the bad/good clients.

Preface

In Kernel code, there's a hash table with request socket queues as entries. Whenever the new sock request (SYN-package) comes, it's inserted into this queue-entry hash table.
However, of course, the capability is limit, Kernel has to dropped some request sockets to allow new sockets with the table is full. In the original Kernel code, it kills old sockets every 0.2 second in net/ipv4/inet_connection_sock.c:inet_csk_reqsk_queue_prune.
Comparing to the original code, in this last OSDI lab, we are not relied on the regular routine to drop old request sockets, but we are randomly dropping a socket in the table when a new socket request comes and the table is full.

Implementation

Modify the Original Pruning Routine

In net/ipv4/inet_connection_sock.c:inet_csk_reqsk_queue_prune add following in line 513:
        thresh = max_retries;
    

Randomly Dropping Socket when Is Full

After tracing the code, we know that the function reqsk_queue_is_full is called whenever the TCP program wants to add a new sock in the request queue. So we simply add some code in the this function.
static inline int reqsk_queue_is_full(struct request_sock_queue *queue)
{
    struct listen_sock *lopt = queue->listen_opt;
    struct request_sock **reqp, *req;
    int i, range, random;
    unsigned long now = jiffies;

    int r = (queue->listen_opt->qlen >> queue->listen_opt->max_qlen_log);

    printk("[OSDI] qlen = %d\n", lopt->qlen);
    if( r ) {

        range = lopt->nr_table_entries;
        printk("range = %d\n", range);

        random %= range;
        get_random_bytes(&random, sizeof(range));

        i = lopt->clock_hand;
        do {
            i = (i + 1) & (lopt->nr_table_entries - 1);
        } while (--random > 0);

        printk("i=%d first is killed\n", i);

        reqp=&lopt->syn_table[i];
        if ((req = *reqp) != NULL) {
            if (time_after_eq(now, req->expires)) {
                /* OSDI lab12 */
                reqsk_queue_unlink(queue, req, reqp);
                reqsk_queue_removed(queue, req);
                reqsk_free(req);
            }
        }
        lopt->clock_hand = i;

    }

    // get the result again
    return queue->listen_opt->qlen >> queue->listen_opt->max_qlen_log;
}
    
We first calculate the original result for is_full or not. If it's full, then we random pick on queue entry from the table and drop the first element of the queue.

Test

Method 1 - Use iptables (Firewall)

Use both simple user socket programs on two machines. One is the client, another is the server. Make sure they can connect at the beginning (the routing is okay between these two machines/VMs). Then, drop any packets from the server on the client by setting up the firewall so that we will only send SYN-packages to the server.
sudo iptables -A INPUT -s <SERVER_IP> -j REJECT

Method 2 - Use hping3

sudo hping3 -i u1 -S -c 10 <SERVER_IP>

Another DDOS Experiment in our Workshop


The attacked server (right-hand side) is having a high CPU usage while another server (left-hand side) is send SYN Flood packages.