HTTP Session

Contents

HTTP Session

Synopsis

The "session" module provides the function of tracing HTTP requests.
The other security modules, such as Cookie Poisoning, will process packets based on this module.
The "session" module records session information by setting a cookie in the client browser.

Directives

session

Syntax session on | off;
Default off
Context Server

Enable or disable session. This directive must present below session_max_size.

Example:

session on;


session_timeout

'Syntax session_timeout timeout;
Default 60
Context Server

Sets the session timeout, in seconds.

Example:

session_timeout 600;


session_max_size

Syntax session_max_size number;
Default
Context HTTP

Set the maximum number of session.

Example:

session_max_size 10000;

session_cookie_name

Syntax session_cookie_name name;
Default SENGINX-SESSION-ID
Context HTTP/Server/Location

Set the name of session cookie.

Example:

session_cookie_name session-id;

session_redirect_timeout

Syntax session_redirect_timeout timeout;
Default 5
Context HTTP/Server/Location

Set the waiting time after SEnginx sends the redirect response to client, in second. This timeout must greater than the value of session timeout.

Example:

session_redirect_timeout 600;

session_show

Syntax session_show on | off;
Default off
Context Location

Show all session information of SEnginx in this location. it's necessary to enable session in the location's server block to use this directive.
You can use a browser to navigate this location to view the session information.
Example:

location /show_session {
      session_show on;
}

How to use Session API to develop modules

Session module provides a set of functions, which are used by modules that based on session module. In fact, session is a place to store data, other modules can store their own run-time data on session node, and the module can use the data stored in session at proper time. The main APIs are as below:

void * ngx_http_session_shm_alloc(size_t size);
 
void ngx_http_session_shm_free(void *);
 
void * ngx_http_session_shm_alloc_nolock(size_t size);
 
void ngx_http_session_shm_free_nolock(void *);
 
ngx_http_session_ctx_t * ngx_http_session_create_ctx(ngx_http_session_t *session, u_char *name, ngx_int_t (*init)(void *ctx), void (*destroy)(void *data));
 
ngx_http_session_ctx_t * ngx_http_session_find_ctx(ngx_http_session_t *session, u_char *name);
 
void ngx_http_session_destroy_ctx(ngx_http_session_t *session, u_char *name);
 
ngx_http_session_t * ngx_http_session_get(ngx_http_request_t *r);
 
void ngx_http_session_put(ngx_http_request_t *r);
 
ngx_int_t ngx_http_session_is_enabled(ngx_http_request_t *r);

void ngx_http_session_register_create_ctx_handler(ngx_http_session_create_ctx_t handler);

Now we show how to use these APIs in detail:

Register the create-ctx callback function

Firstly, you need to register a callback function which will be called when a session is created. This function should contain the functionality that create your own module's session ctx.
For instance, in the cookie poisoning module, we register the callback function as this:

static ngx_int_t                                                                                                         
ngx_http_cp_filter_init(ngx_conf_t *cf)                                                                                  
{                                                                                                                        
    ngx_int_t ret;                                                                                                       
                                                                                                                         
    ret = ngx_http_neteye_security_header_register(                                                                      
            NGX_HTTP_NETEYE_COOKIE_POISONING, ngx_http_cp_header_handler);                                               
                                                                                                                         
    if (ret == NGX_ERROR) {                                                                                              
        return NGX_ERROR;                                                                                                
    }                                                                                                                    
                                                                                                                         
    ngx_http_session_register_create_ctx_handler(                                                                        
            ngx_http_cp_create_session_ctx);                                                                             
                                                                                                                         
    return ngx_http_neteye_security_request_register(                                                                    
            NGX_HTTP_NETEYE_COOKIE_POISONING, ngx_http_cp_handler);                                                      
}  

Thereinto, a typical implementation of "ngx_http_cp_create_session_ctx" could be:

static void
ngx_http_cp_create_session_ctx(ngx_http_session_t *session)
{
    ngx_http_session_ctx_t           *session_ctx;
    ngx_http_cp_session_ctx_t        *cp_ctx;

    session_ctx = ngx_http_session_create_ctx(session,
            (u_char *)"cookie_poisoning",
            ngx_http_cp_init_session_ctx_handler,
            ngx_http_cp_destroy_session_ctx_handler);
    if (!session_ctx) {
        return;
    }

    /* init cp_ctx */
    cp_ctx = session_ctx->data;

    cp_ctx->bl_times = 0;
    ngx_http_cp_hash_init(&cp_ctx->monitored_cookies,
            NGX_HTTP_CP_DEFAULT_BUCKETS_NUM);
}

You should provide 2 callback handlers for ngx_http_session_create_ctx function, for initialising and destorying perspectively.

Store data in session

1. First, you need to get session node:

session = ngx_http_session_get(r);

2. Then you need to lock this session before other actions:

ngx_shmtx_lock(&session->mutex);

3. find the ctx structure from session node. the ctx structure is where the data really stores in session node:

session_ctx = ngx_http_session_find_ctx(session, action->session_name);
the ctx structure is created by session-based module, and it's stored in session node. The unique identifier of ctx structure is the name of ctx.

4. if there is no ctx available in this session node, then you need to create one:

session_ctx = ngx_http_session_create_ctx(session, 
                        action->session_name, 
                        action->init,
                        action->destroy);
ngx_http_session_create_ctx function accepts two function pointers, which are used to initialize and destroy the ctx of this module correspondingly.

5. use the ctx structure in the session-based module.
6. When finishing the use of ctx structure, unlock session node and decrease the reference count:

ngx_shmtx_unlock(&session->mutex);
ngx_http_session_put(r);

The init function and destroy function in ngx_http_session_create_ctx

Below is the init nad destroy functions from robot mitigation module:

static void
ngx_http_rm_destroy_ctx_handler(void *ctx)
{
    ngx_http_session_ctx_t *session_ctx;                                                                                
                                                                                                                         
    session_ctx = (ngx_http_session_ctx_t *)ctx;                                                                        
                                                                                                                         
    return ngx_http_session_shm_free_nolock(session_ctx->data);                                                         
}                                                                                                                       
                                                                                                                         
static ngx_int_t                                                                                                        
ngx_http_rm_init_ctx_handler(void *ctx)                                                                                 
{                                                                                                                       
    ngx_http_session_ctx_t *session_ctx;                                                                                
                                                                                                                         
    session_ctx = (ngx_http_session_ctx_t *)ctx;                                                                        
                                                                                                                         
    /* initial session ctx */                                                                                          
    session_ctx->data =                                                                                                 
        ngx_http_session_shm_alloc_nolock(sizeof(ngx_http_rm_session_ctx_t));                                           
    if (!session_ctx->data) {                                                                                           
        fprintf(stderr, "create ac ctx error\n");                                                                       
        return NGX_ERROR;                                                                                               
    }                                                                                                                   
                                                                                                                         
    memset(session_ctx->data, 0, sizeof(ngx_http_rm_session_ctx_t));                                                    
                                                                                                                         
    return NGX_OK;                                                                                                      
}

The memory is allocated in the shared memory zone, thus you need to use the ngx_http_session_shm_alloc/free series functions.