Nginx-ru mailing list archive (nginx-ru@sysoev.ru)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: nginx apache2 (rpaf-0.6)
> Да, есть такая проблема.
> В свое время я тоже с этим стоклнулся. Ставил syslog-и в mod_authz_host
> оказалось, что в этом модуле адрес остается неизменным (адрес nginx с
> которого было установлено соединение) в то время как в логах и
> $_SERVER['REMOTE_ADDR'] был верный адрес из X-Real-IP.
>
> Имхо, тут apache крутить надо. У меня мозга не хватило =)
В своё время тоже столкнулся с непонятным поведением mod_rpaf.
Что побудило написать свой модуль. Можете попробовать мой.
В аттаче src.rpm для CentOS и сам исходник модуля для не rpm-based систем.
src.rpm пересобирается как обычно.
Исходник так:
$ apxs -c mod_realip2.c
Собственно о модуле:
Название mod_realip2. Это чтобы не путать с модулем просто mod_realip от Игоря
Сысоева.
Двоечка также подчеркивает то, что модуль предназначен для апача 2.
Есть совместимость с IPv6. Правда в бою не проверял, только тестировал.
Модуль не поддерживает формат заголовка типа X-Forwarded-For.
Использование:
# Загрузка модуля
LoadModule realip2_module MODULES_DIR/mod_realip2.so
# Включает модуль
RealIP On
# Список адресов для коотрых делать перезапись ИП (можно ИП, можно и ДНС имя)
RealIPProxy 127.0.0.1 10.0.3.3
# В каком заголовке искать ИП адрес (по дефолту X-Real-IP)
RealIPHeader X-Real-IP
Соответственно в nginx:
proxy_pass http://...;
proxy_set_header X-Real-IP $remote_addr;
Attachment:
mod_realip2-1.1-1.el5.centos.src.rpm
Description: application/rpm
/*
* mod_realip2
* Olexander Shtepa
* Changelog:
* 1.1 - Move the `realip2_post_read_request' handler from being
APR_HOOK_MIDDLE to
APR_HOOK_FIRST to make the module run before modules like mod_geoip.
(from mod_rpaf)
* 1.0 - Initial release.
*/
#include <string.h>
#include <arpa/inet.h>
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "apr_pools.h"
#include "apr_strings.h"
#include "apr_tables.h"
#define REALIP2_STATUS_UNDEFINED 0
#define REALIP2_STATUS_ON 1
#define REALIP2_STATUS_OFF 2
#ifdef REALIP2_VERSION_SHOW
# define REALIP2_VERSION "1.1"
#endif
static const char* realip2_default_header="X-Real-IP";
module AP_MODULE_DECLARE_DATA realip2_module;
typedef struct
{
int status;
apr_array_header_t* proxy_addrs;
const char* header;
} realip2_server_cfg;
static int realip2_match_proxy(const request_rec* r, const realip2_server_cfg*
cfg)
{
int i;
int nelts=cfg->proxy_addrs->nelts;
const apr_sockaddr_t** proxy_addrs=(const
apr_sockaddr_t**)cfg->proxy_addrs->elts;
const apr_sockaddr_t* remote_addr=r->connection->remote_addr;
for(i=0;i<nelts;++i)
if (apr_sockaddr_equal(remote_addr,proxy_addrs[i]))
return 1;
return 0;
}
static void realip2_replace_ip(request_rec* r, const char* new_ip)
{
struct in_addr sin_addr;
#if APR_HAVE_IPV6
struct in6_addr sin6_addr;
#endif
apr_sockaddr_t* remote_addr=r->connection->remote_addr;
if (inet_pton(APR_INET,new_ip,&sin_addr)>0)
{
#if APR_HAVE_IPV6
if (remote_addr->family==APR_INET6)
{
remote_addr->family=APR_INET;
remote_addr->salen=sizeof(struct sockaddr_in);
remote_addr->addr_str_len=16;
remote_addr->ipaddr_len=sizeof(struct in_addr);
remote_addr->ipaddr_ptr=&remote_addr->sa.sin.sin_addr;
memset(&remote_addr->sa,0,sizeof(struct sockaddr_in));
remote_addr->sa.sin.sin_family=APR_INET;
remote_addr->sa.sin.sin_port=htons(remote_addr->port);
}
#endif
remote_addr->sa.sin.sin_addr.s_addr=sin_addr.s_addr;
}
#if APR_HAVE_IPV6
else if (inet_pton(APR_INET6,new_ip,&sin6_addr)>0)
{
if (remote_addr->family==APR_INET)
{
remote_addr->family=APR_INET6;
remote_addr->salen=sizeof(struct sockaddr_in6);
remote_addr->addr_str_len=46;
remote_addr->ipaddr_len=sizeof(struct in6_addr);
remote_addr->ipaddr_ptr=&remote_addr->sa.sin6.sin6_addr;
memset(&remote_addr->sa,0,sizeof(struct sockaddr_in6));
remote_addr->sa.sin6.sin6_family=APR_INET6;
remote_addr->sa.sin6.sin6_port=htons(remote_addr->port);
}
memcpy(&remote_addr->sa.sin6.sin6_addr,&sin6_addr,sizeof(struct
in6_addr));
}
#endif
else
/* The new IP address does not valid */
return;
r->connection->remote_ip=apr_pstrdup(remote_addr->pool,new_ip);
}
static int realip2_post_read_request(request_rec* r)
{
const realip2_server_cfg*
cfg=(realip2_server_cfg*)ap_get_module_config(r->server->module_config,&realip2_module);
if (cfg->status==REALIP2_STATUS_ON && realip2_match_proxy(r,cfg))
{
const char* real_ip=apr_table_get(r->headers_in,cfg->header);
if (real_ip)
realip2_replace_ip(r,real_ip);
}
return DECLINED;
}
#ifdef REALIP2_VERSION_SHOW
static int realip2_post_config(apr_pool_t* pconf, apr_pool_t* plog, apr_pool_t*
ptemp, server_rec* s)
{
ap_add_version_component(pconf,"mod_realip2/" REALIP2_VERSION);
return OK;
}
#endif
static void* realip2_create_server_config(apr_pool_t* p, server_rec* s)
{
realip2_server_cfg*
cfg=(realip2_server_cfg*)apr_palloc(p,sizeof(realip2_server_cfg));
cfg->status=REALIP2_STATUS_UNDEFINED;
cfg->proxy_addrs=apr_array_make(p,0,sizeof(apr_sockaddr_t*));
cfg->header=realip2_default_header;
return (void*)cfg;
}
static void* realip2_merge_server_config(apr_pool_t* p, void* def_cfg, void*
new_cfg)
{
realip2_server_cfg* def=(realip2_server_cfg*)def_cfg;
realip2_server_cfg* new=(realip2_server_cfg*)new_cfg;
realip2_server_cfg*
cfg=(realip2_server_cfg*)apr_palloc(p,sizeof(realip2_server_cfg));
cfg->status=(new->status==REALIP2_STATUS_UNDEFINED)?def->status:new->status;
cfg->proxy_addrs=apr_is_empty_array(new->proxy_addrs)?def->proxy_addrs:new->proxy_addrs;
cfg->header=(new->header==realip2_default_header)?def->header:new->header;
return (void*)cfg;
}
static const char* realip2_set_realip(cmd_parms* cmd, void* mconfig, int value)
{
realip2_server_cfg*
cfg=(realip2_server_cfg*)ap_get_module_config(cmd->server->module_config,&realip2_module);
cfg->status=value?REALIP2_STATUS_ON:REALIP2_STATUS_OFF;
return NULL;
}
static const char* realip2_set_realipproxy(cmd_parms* cmd, void* mconfig, const
char* host)
{
apr_status_t err;
realip2_server_cfg*
cfg=(realip2_server_cfg*)ap_get_module_config(cmd->server->module_config,&realip2_module);
apr_sockaddr_t** new_host=apr_array_push(cfg->proxy_addrs);
/* Resolve host */
err=apr_sockaddr_info_get(new_host,host,APR_UNSPEC,0,0,cmd->pool);
if (err!=APR_SUCCESS)
return apr_pstrcat(cmd->pool,"Cannot resolve host name:
",host,NULL);
/* Add all aditional addresses */
while((*new_host)->next)
{
apr_sockaddr_t* next=(*new_host)->next;
new_host=apr_array_push(cfg->proxy_addrs);
*new_host=next;
}
return NULL;
}
static const char* realip2_set_realipheader(cmd_parms* cmd, void* mconfig,
const char* header)
{
realip2_server_cfg*
cfg=(realip2_server_cfg*)ap_get_module_config(cmd->server->module_config,&realip2_module);
cfg->header=header;
return NULL;
}
static const command_rec realip2_cmds[]=
{
AP_INIT_FLAG(
"RealIP",
realip2_set_realip,
NULL,
RSRC_CONF,
"Enable remote IP rewriting by a real value"
),
AP_INIT_ITERATE(
"RealIPProxy",
realip2_set_realipproxy,
NULL,
RSRC_CONF,
"Set hosts that can rewrite a real remote IP"
),
AP_INIT_TAKE1(
"RealIPHeader",
realip2_set_realipheader,
NULL,
RSRC_CONF,
"Watch this header for a real IP value"
),
{NULL}
};
static void realip2_register_hooks(apr_pool_t* p)
{
#ifdef REALIP2_VERSION_SHOW
ap_hook_post_config(realip2_post_config,NULL,NULL,APR_HOOK_MIDDLE);
#endif
ap_hook_post_read_request(realip2_post_read_request,NULL,NULL,APR_HOOK_FIRST);
}
module AP_MODULE_DECLARE_DATA realip2_module=
{
STANDARD20_MODULE_STUFF,
NULL,
NULL,
realip2_create_server_config,
realip2_merge_server_config,
realip2_cmds,
realip2_register_hooks,
};
|