Session

Contents

Обзор

Модуль Session обеспечивает функцию отслеживания HTTP-запросов.
Другие модули безопасности, такие как Cookie Poisoning, обрабатывают запросы с использованием этого модуля.
Модуль Session записывает информацию о сессии, устанавливая cookie в клиентском браузере.

Директивы

session

Синтаксис session on | off;
По умолчанию off
Контекст Server

Включить или выключить модуль Session. При включении Session также должно быть задано значение session_max_size.

Пример:

session on;


session_timeout

Синтаксис session_timeout timeout;
По умолчанию 60
Контекст Server

Устанавливает таймаут сессии в секундах.

Пример:

session_timeout 600;


session_max_size

Синтаксис session_max_size number;
По умолчанию
Контекст http

Устанавливает максимальное количество сессий.

Пример:

session_max_size 10000;


session_cookie_name

Синтаксис session_cookie_name name;
По умолчанию SENGINX-SESSION-ID
Контекст http/Server/Location

Устанавливает имя сессионного cookie.

Пример:

session_cookie_name session-id;


session_redirect_timeout

Синтаксис session_redirect_timeout timeout;
По умолчанию 5
Контекст http/Server/Location

Устанавливает время ожидания в секундах, после которого SEnginx отправляет клиенту ответ с редиректом. Этот таймаут должен быть больше, чем значение session_timeout.

Пример:

session_redirect_timeout 700;


session_show

Синтаксис session_show on | off;
По умолчанию off
Контекст Location

Показывать в этом location информацию о всех сессиях SEnginx. Для того, чтобы использовать эту директиву, необходимо включить session в блоке server, в который входит данный location.
Вы можете открыть этот location в браузере, чтобы просмотреть информацию о сессиях.
Пример:

location /show_session {
      session_show on;
}


Использование Session API для разработки модулей

Модуль Session предоставляет набор функций, которые используются другими модулями. Фактически модуль Session это место, в котором другие модули могут хранить сессионные данные во время своей работы. Основные функции API:

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);

Далее показано как использовать эти функции:

Регистрация create-ctx callback функции

Сначала нужно зарегистрировать callback-функцию, которая будет вызываться при создании сессии. Эта функция должна создавать session ctx для вашего модуля.
Например, в модуле Cookie Poisoning мы регистрируем callback-функцию следующим образом:

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);                                                      
}  

Реализация "ngx_http_cp_create_session_ctx" может выглядеть так:

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);
}

Вы должны обеспечить 2 callback-обработчика для функции ngx_http_session_create_ctx - для инициализации и удаления соответственно.

Хранение данных в сессии

1. Получить сессию:

session = ngx_http_session_get(r);

2. Заблокирвать сессию до выполнения каких-то действий:

ngx_shmtx_lock(&session->mutex);

3. Получить из сессии структуру ctx, в которой хранятся данные:

session_ctx = ngx_http_session_find_ctx(session, action->session_name);
Структура ctx создается модулем, основанным на использовании сессии. Уникальный идентификатор структуры ctx это имя ctx.

4. Если в сессии нет ни одной структуры ctx, нужно ее создать:

session_ctx = ngx_http_session_create_ctx(session, 
                        action->session_name, 
                        action->init,
                        action->destroy);
Функция ngx_http_session_create_ctx принимает указатели на две функции, которые используются соответственно для создания и удаления структуры ctx.

5. Использовать структуру ctx в модуле.
6. По окончании использования структуры ctx нужно разблокировать сессию и уменьшить счетчик ссылок:

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

Функции init и destroy в ngx_http_session_create_ctx

Функции init и destroy из модуля Robot Mitigation:

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;                                                                                                      
}

Память выделяется в зоне разделямой памяти, поэтому нужно использовать функции ngx_http_session_shm_alloc/free.