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"
Если требуется описание и примеры использования функций - пишите.
/*
* 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
|