ПРОЕКТЫ 


  АРХИВ 


Apache-Talk @lexa.ru 

Inet-Admins @info.east.ru 

Filmscanners @halftone.co.uk 

Security-alerts @yandex-team.ru 

nginx-ru @sysoev.ru 


  СТАТЬИ 


  ПЕРСОНАЛЬНОЕ 


  ПРОГРАММЫ 



ПИШИТЕ
ПИСЬМА












     АРХИВ :: nginx-ru
Nginx-ru mailing list archive (nginx-ru@sysoev.ru)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Скрестить nginx с ipset



Вот набор функций по управлению таблицами PF, программист я не ахти, но функции работают.
Чтобы использовать в модулях нужно добавить #include <ngx_pfctl.h> и при инициализации модуля необходимо открыть /dev/pf на чтение/запись.

Файлы положить в src/os/unix/, при компиляции наложить патч:
Index: trunk/nginx-0.8.54/auto/sources
===================================================================
--- a/trunk/nginx-0.8.54/auto/sources
+++ b/trunk/nginx-0.8.54/auto/sources
@@ -146,4 +146,5 @@
             src/os/unix/ngx_os.h \
             src/os/unix/ngx_user.h \
+           src/os/unix/ngx_pfctl.h \
             src/os/unix/ngx_process_cycle.h"
 
@@ -176,4 +177,5 @@
             src/os/unix/ngx_posix_init.c \
             src/os/unix/ngx_user.c \
+           src/os/unix/ngx_pfctl.c \
             src/os/unix/ngx_process_cycle.c"

Если требуется описание и примеры использования функций - пишите.

24 мая 2011 г. 10:39 пользователь InventOR <nginx-forum@xxxxxxxx> написал:
также неплохо бы было подобное
прикрутить к *BSD PF фильтру.
Пока такое делается через анализ лога
демоном и выпарсиванием оттуда
ИПшника.

Posted at Nginx Forum: http://forum.nginx.org/read.php?21,200292,200299#msg-200299


_______________________________________________
nginx-ru mailing list
nginx-ru@xxxxxxxxx
http://nginx.org/mailman/listinfo/nginx-ru

/*
 * Copyright (C) Nikita Kozlov
 */


#include <ngx_core.h>
#include <ngx_pfctl.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <net/pfvar.h>
#include <stdio.h>
#include <stdlib.h>


int
ngx_pfctl_table_add_addr(int pf_dev, ngx_cidr_t *cidr, ngx_str_t *pf_table, 
ngx_str_t *pf_anchor, ngx_log_t *log)
{
    struct pfioc_table  io;
    struct pfr_addr     addr;

    if (pf_table == NULL)
        return NGX_ERROR;

    bzero(&io, sizeof(io));
    ngx_cpystrn(io.pfrio_table.pfrt_name, pf_table->data, pf_table->len + 1);
    ngx_cpystrn(io.pfrio_table.pfrt_anchor, pf_anchor->data, pf_anchor->len + 
1);

    io.pfrio_buffer = &addr;
    io.pfrio_esize = sizeof(addr);
    io.pfrio_size = 1;

    bzero(&addr, sizeof(addr));
    bcopy(&cidr->u.in.addr, &addr.pfra_ip4addr, 4);
    addr.pfra_af = AF_INET;
    addr.pfra_net = ngx_pfctl_ltoprefix(cidr->u.in.mask);

    if (ioctl(pf_dev, DIOCRADDADDRS, &io)) {
        ngx_log_error(NGX_LOG_ERR, log, ngx_errno,
                "ngx_pfctl: failed to DIOCRADDADDRS");
        return NGX_ERROR;
    }

    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, log, 0,
            "ngx_pfctl: add \"%d\" address(es) to PF table \"%V\" of \"%V\" 
anchor", io.pfrio_nadd, pf_table, pf_anchor);

    return io.pfrio_nadd;
}


int
ngx_pfctl_table_del_addr(int pf_dev, ngx_cidr_t *cidr, ngx_str_t *pf_table, 
ngx_str_t *pf_anchor, ngx_log_t *log)
{
    struct pfioc_table  io;
    struct pfr_addr     addr;

    if (pf_table == NULL)
        return NGX_ERROR;

    bzero(&io, sizeof(io));
    ngx_cpystrn(io.pfrio_table.pfrt_name, pf_table->data, pf_table->len + 1);
    ngx_cpystrn(io.pfrio_table.pfrt_anchor, pf_anchor->data, pf_anchor->len + 
1);

    io.pfrio_buffer = &addr;
    io.pfrio_esize = sizeof(addr);
    io.pfrio_size = 1;

    bzero(&addr, sizeof(addr));
    bcopy(&cidr->u.in.addr, &addr.pfra_ip4addr, 4);
    addr.pfra_af = AF_INET;
    addr.pfra_net = ngx_pfctl_ltoprefix(cidr->u.in.mask);

    if (ioctl(pf_dev, DIOCRDELADDRS, &io)) {
        ngx_log_error(NGX_LOG_ERR, log, ngx_errno,
            "ngx_pfctl: failed to DIOCRDELADDRS");
        return NGX_ERROR;
    }

    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, log, 0,
        "ngx_pfctl: del \"%d\" address(es) from PF table \"%V\" of \"%V\" 
anchor", io.pfrio_ndel, pf_table, pf_anchor);

    return io.pfrio_ndel;
}


int
ngx_pfctl_table_test_addr(int pf_dev, ngx_cidr_t *cidr, ngx_str_t *pf_table, 
ngx_str_t *pf_anchor, ngx_log_t *log)
{
    struct pfioc_table  io;
    struct pfr_addr     addr;

    if (pf_table == NULL)
        return NGX_ERROR;

    bzero(&io, sizeof(io));
    ngx_cpystrn(io.pfrio_table.pfrt_name, pf_table->data, pf_table->len + 1);
    ngx_cpystrn(io.pfrio_table.pfrt_anchor, pf_anchor->data, pf_anchor->len + 
1);

    io.pfrio_buffer = &addr;
    io.pfrio_esize = sizeof(addr);
    io.pfrio_size = 1;

    bzero(&addr, sizeof(addr));
    bcopy(&cidr->u.in.addr, &addr.pfra_ip4addr, 4);
    addr.pfra_af = AF_INET;
    addr.pfra_net = ngx_pfctl_ltoprefix(cidr->u.in.mask);

    if (ioctl(pf_dev, DIOCRTSTADDRS, &io)) {
        ngx_log_error(NGX_LOG_ERR, log, ngx_errno,
                "ngx_pfctl: failed to DIOCRTSTADDRS");
        return NGX_ERROR;
    }

    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, log, 0,
            "ngx_pfctl: test \"%d\" address(es) from PF table \"%V\" of \"%V\" 
anchor", io.pfrio_ndel, pf_table, pf_anchor);

    return ((struct pfr_addr *) io.pfrio_buffer)->pfra_fback;
}


int
ngx_pfctl_table_flush(int pf_dev, ngx_str_t *pf_table, ngx_str_t *pf_anchor, 
ngx_log_t *log)
{
    struct pfioc_table  io;

    if (pf_table == NULL)
        return NGX_ERROR;

    bzero(&io, sizeof(io));
    ngx_cpystrn(io.pfrio_table.pfrt_name, pf_table->data, pf_table->len + 1);
    ngx_cpystrn(io.pfrio_table.pfrt_anchor, pf_anchor->data, pf_anchor->len + 
1);

    if (ioctl(pf_dev, DIOCRCLRADDRS, &io)) {
        ngx_log_error(NGX_LOG_ERR, log, ngx_errno,
            "ngx_pfctl: failed to DIOCRCLRADDRS");
        return NGX_ERROR;
    }

    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, log, 0,
        "ngx_pfctl: flush \"%d\" address(es) from PF table \"%V\" of \"%V\" 
anchor", io.pfrio_ndel, pf_table, pf_anchor);

    return io.pfrio_ndel;
}


int
ngx_pfctl_kill_states(int pf_dev, struct in_addr s_ip, struct in_addr d_ip, 
ngx_log_t *log)
{
    struct pfioc_state_kill psk;
    struct pf_addr source_addr, destination_addr;

    memset(&psk, 0, sizeof(psk));
    memset(&source_addr, 0, sizeof(source_addr));
    memset(&destination_addr, 0, sizeof(destination_addr));

    psk.psk_af = AF_INET;

    source_addr.v4 = s_ip;
    destination_addr.v4 = d_ip;

    memcpy(&psk.psk_src.addr.v.a.addr, &source_addr,
        sizeof(psk.psk_src.addr.v.a.addr));
    memset(&psk.psk_src.addr.v.a.mask, 0xff,
        sizeof(psk.psk_src.addr.v.a.mask));
    memcpy(&psk.psk_dst.addr.v.a.addr, &destination_addr,
        sizeof(psk.psk_dst.addr.v.a.addr));
    memset(&psk.psk_dst.addr.v.a.mask, 0xff,
        sizeof(psk.psk_dst.addr.v.a.mask));


    if (ioctl(pf_dev, DIOCKILLSTATES, &psk)) {
        ngx_log_error(NGX_LOG_ERR, log, ngx_errno,
                "ngx_pfctl: failed to DIOCKILLSTATES");
        return NGX_ERROR;
    }


    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
            "ngx_pfctl: kill \"%d\" PF states", psk.psk_af);

    return (int) psk.psk_af;
}


int
ngx_pfctl_test_anchor(int pf_dev, ngx_str_t *pf_anchor, ngx_log_t *log)
{
    struct pfioc_ruleset     pr;

    bzero(&pr, sizeof(pr));
    ngx_cpystrn(pr.path, pf_anchor->data, pf_anchor->len + 1);
    if (ioctl(pf_dev, DIOCGETRULESETS, &pr)) {
        if (errno == EINVAL)
            return 0;
        else
            return NGX_ERROR;
    }
    return 1;
}


int
ngx_pfctl_test_table(int pf_dev, ngx_str_t *pf_anchor, ngx_str_t *pf_table, 
ngx_log_t *log)
{
        struct pfioc_table io;
        struct pfr_table     tables[10], filter;
        int                  rc, i, n, t;

        bzero(&filter, sizeof(filter));
        ngx_cpystrn(filter.pfrt_name, pf_table->data, pf_table->len + 1);

        if (pf_anchor->len)
            ngx_cpystrn(filter.pfrt_anchor, pf_anchor->data, pf_anchor->len + 
1);

        bzero(&io, sizeof io);
        io.pfrio_table = filter;
        io.pfrio_buffer = tables;
        io.pfrio_esize = sizeof(struct pfr_table);
        io.pfrio_size = 10;
        if (rc = ioctl(pf_dev, DIOCRGETTABLES, &io)) {
                ngx_log_error(NGX_LOG_ERR, log, ngx_errno,
                        "ngx_pfctl: failed to DIOCRGETTABLES");
                return NGX_ERROR;
        }
        for (i = 0; i < io.pfrio_size; i++) {
            n = 0;
            for (t = 0; t < PF_TABLE_NAME_SIZE; t++) {
                if (tables[i].pfrt_name[t] == '\0') {
                    break;
                }
                n++;
            }
            if (n != pf_table->len) {
                continue;
            }
            if (ngx_strncmp(tables[i].pfrt_name, pf_table->data, pf_table->len) 
== 0) {
                return 1;
            }
            continue;
        }
        return NGX_ERROR;
}

int
ngx_pfctl_get_addrs(int pf_dev, ngx_str_t *pf_anchor, ngx_str_t 
*pf_table,ngx_pfctl_addr_buf_t *pf_addrs, ngx_pool_t *pool, ngx_log_t *log)
{
    struct pfioc_table       io;
    size_t                   rc, msize = NGX_PFCTL_BUF_MSIZE;
    struct pfr_addr         *buf = NULL;

    bzero(&io, sizeof(struct pfioc_table));

    ngx_cpystrn(io.pfrio_table.pfrt_name, pf_table->data, pf_table->len + 1);

    if (pf_anchor->data != NULL)
        strlcpy(io.pfrio_table.pfrt_anchor, pf_anchor->data, pf_anchor->len + 
1);

    get:
    if (buf != NULL) {
        if (ngx_pfree(pool, buf) == NGX_DECLINED){
            /* sanity check */
            ngx_log_error(NGX_LOG_ERR, log, 0,
                    "ngx_pfctl: failed to free allocated buffer");
        }
    }

    buf = ngx_pcalloc(pool, sizeof(struct pfr_addr) * msize);
    if (buf == NULL) {
        ngx_log_error(NGX_LOG_ERR, log, 0,
                "ngx_pfctl: failed to allocate buffer");
        return NGX_ERROR;
    }

    io.pfrio_buffer = buf;
    io.pfrio_esize = sizeof(struct pfr_addr);
    io.pfrio_size = msize;

    if (rc = ioctl(pf_dev, DIOCRGETADDRS, &io)) {
        ngx_log_error(NGX_LOG_ERR, log, ngx_errno,
                "ngx_pfctl: failed to DIOCRGETADDRS");
        return NGX_ERROR;
    }

    if (io.pfrio_size > msize) {
        msize = io.pfrio_size;
        goto get;
    }

    pf_addrs->buf = buf;
    pf_addrs->len = io.pfrio_size;

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
            "ngx_pfctl: get \"%d\" IP address(es)", io.pfrio_size);

    return  NGX_OK;
}


int
ngx_pfctl_ltoprefix(in_addr_t mask)
{
    ngx_uint_t        i;

    for (i = 0; mask !=0; i++) {
        mask >>= 1;
    }

    return i;
}
/*
 * Copyright (C) Nikita Kozlov
 */


#ifndef _NGX_PFCTL_H_INCLUDED_
#define _NGX_PFCTL_H_INCLUDED_

#define NGX_PFCTL_BUF_MSIZE 1;


#include <ngx_core.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <net/pfvar.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    size_t               len;
    struct pfr_addr     *buf;
} ngx_pfctl_addr_buf_t;


int ngx_pfctl_table_add_addr(int pf_dev, ngx_cidr_t *cidr, ngx_str_t *pf_table, 
ngx_str_t *pf_anchor, ngx_log_t *log);
int ngx_pfctl_table_del_addr(int pf_dev, ngx_cidr_t *cidr, ngx_str_t *pf_table, 
ngx_str_t *pf_anchor, ngx_log_t *log);
int ngx_pfctl_table_test_addr(int pf_dev, ngx_cidr_t *cidr, ngx_str_t 
*pf_table, ngx_str_t *pf_anchor, ngx_log_t *log);
int ngx_pfctl_table_flush(int pf_dev, ngx_str_t *pf_table, ngx_str_t 
*pf_anchor, ngx_log_t *log);
int ngx_pfctl_kill_states(int pf_dev, struct in_addr s_ip, struct in_addr d_ip, 
ngx_log_t *log);
int ngx_pfctl_test_anchor(int pf_dev, ngx_str_t *pf_anchor, ngx_log_t *log);
int ngx_pfctl_test_table(int pf_dev, ngx_str_t *pf_anchor, ngx_str_t *pf_table, 
ngx_log_t *log);
int ngx_pfctl_get_addrs(int pf_dev, ngx_str_t *pf_anchor, ngx_str_t 
*pf_table,ngx_pfctl_addr_buf_t *addr_buf, ngx_pool_t *pool, ngx_log_t *log);
int ngx_pfctl_ltoprefix(in_addr_t mask);

#endif /* _NGX_PFCTL_H_INCLUDED_ */
_______________________________________________
nginx-ru mailing list
nginx-ru@xxxxxxxxx
http://nginx.org/mailman/listinfo/nginx-ru


 




Copyright © Lexa Software, 1996-2009.