On Fri, 20 Oct 2000, Alex Znamerovskiy wrote:
> ������: http://apache.lexa.ru
> � ����� ��� ���:
> 972016542.000 3394 10.3.1.215 TCP_REFRESH_MISS/200 13552 GET
> http://apache.lexa.
> ru/ - NONE/10.3.1.147 text/html
> 972016542.000 1368 10.3.1.215 TCP_MISS/301 517 GET
[skip]
> 972016552.000 1353 10.3.1.215 TCP_MISS/301 527 GET
> http://apache.lexa.ru/buttons
> /but-cr3.gif - PARENT/10.3.1.147 text/html
> [...]
>
> � ��������� �������� �������, ��� ������� ������ �
> http://apache.lexa.ru:8101/buttons/blablabla.gif
> � ��� �����, ��� ����� � 80 �����. ���� � ���� � ��������. (���� ����� �� �
> �� ������ ���� ������).
��, �� ����� ����... � ����-�� ����.
�� ������ ������, ����������, ����������, ��� ���� transparent.c (����������
������������ ��� � 1.4.22 ��� �� ������� ����� ������ ������� oops),
� ���� ������� ������� ���������� Alexander Savelyev <[EMAIL PROTECTED]>.
�������� ��� ��� ������ ��, ��� �����, ������ ��� ��� ���-��� ��� ������ �
ip_filter ���� �������������, ������, �����������, �� � ������ ������
ip_filter ����� ������ ��������� ����� ioctl.
�������, �������� � �����������, � ��� ����� � �������� ����������.
Igor Khasilev |
PACO Links, igor at paco dot net |
/*
Copyright (C) 1999 Igor Khasilev, [EMAIL PROTECTED]
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "../oops.h"
#include "../modules.h"
#if defined(HAVE_IPF)
#if defined(va_start) /* dirty hack. sol7 x86 + gcc 2.95.2 */
#define _SYS_VARARGS_H
#endif
#include <sys/ioctl.h>
#if defined(HAVE_IP6_H)
#include <netinet/ip6.h>
#endif
#include <netinet/tcp.h>
#include <net/if.h>
#include <netinet/ip_compat.h>
#include <netinet/ip_fil.h>
#include <netinet/ip_nat.h>
int natfd;
#endif
#define MODULE_NAME "transparent"
#define MODULE_INFO "Transparent proxy"
#if defined(MODULES)
char module_type = MODULE_REDIR ;
char module_name[] = MODULE_NAME ;
char module_info[] = MODULE_INFO ;
int mod_load();
int mod_unload();
int mod_config_beg(), mod_config_end(), mod_config(), mod_run();
int redir(int so, struct group *group, struct request *rq, int *flags);
#else
static char module_type = MODULE_REDIR ;
static char module_name[] = MODULE_NAME ;
static char module_info[] = MODULE_INFO ;
static int mod_load();
static int mod_unload();
static int mod_config_beg(), mod_config_end(), mod_config(), mod_run();
static int redir(int so, struct group *group, struct request *rq, int *flags);
#endif
struct redir_module transparent = {
{
NULL, NULL,
MODULE_NAME,
mod_load,
mod_unload,
mod_config_beg,
mod_config_end,
mod_config,
NULL,
MODULE_REDIR,
MODULE_INFO,
mod_run
},
redir,
NULL,
NULL
};
static rwl_t tp_lock;
#define RDLOCK_TP_CONFIG rwl_rdlock(&tp_lock)
#define WRLOCK_TP_CONFIG rwl_wrlock(&tp_lock)
#define UNLOCK_TP_CONFIG rwl_unlock(&tp_lock)
#define NMYPORTS 4
static myport_t myports[NMYPORTS]; /* my ports */
static int nmyports; /* actual number */
static char *myports_string;
/* static char *build_src(struct request*); */
int
mod_load()
{
printf("Transparent started\n");
rwl_init(&tp_lock);
nmyports = 0;
#if defined(HAVE_IPF)
natfd = -1;
#endif
myports_string = NULL;
return(MOD_CODE_OK);
}
int
mod_unload()
{
verb_printf("Transparent stopped\n");
return(MOD_CODE_OK);
}
int
mod_config_beg()
{
WRLOCK_TP_CONFIG ;
nmyports = 0;
if ( myports_string ) free(myports_string);
myports_string = NULL;
#if defined(HAVE_IPF)
if ( natfd != -1 ) close(natfd);
natfd = -1;
#endif
UNLOCK_TP_CONFIG ;
return(MOD_CODE_OK);
}
int
mod_run()
{
if ( myports_string ) {
WRLOCK_TP_CONFIG ;
nmyports = parse_myports(myports_string, &myports[0], NMYPORTS);
verb_printf("%s will use %d ports\n", module_name, nmyports);
UNLOCK_TP_CONFIG ;
}
return(MOD_CODE_OK);
}
int
mod_config_end()
{
return(MOD_CODE_OK);
}
int
mod_config(char *config)
{
char *p = config;
WRLOCK_TP_CONFIG ;
while( *p && IS_SPACE(*p) ) p++;
if ( !strncasecmp(p, "myport", 6) ) {
p += 6;
while (*p && IS_SPACE(*p) ) p++;
myports_string = strdup(p);
}
UNLOCK_TP_CONFIG ;
return(MOD_CODE_OK);
}
int
redir(int so, struct group *group, struct request *rq, int *flags)
{
char *host = NULL;
u_short port;
char *dd = NULL;
RDLOCK_TP_CONFIG ;
my_xlog(LOG_DBG, "redir(): redir/transparent called.\n");
if ( !rq ) goto done;
port = ntohs(rq->my_sa.sin_port);
if ( nmyports > 0 ) {
int n = nmyports;
myport_t *mp = myports;
/* if this is not on my port */
while( n ) {
/* if accepted on my socket */
if ( mp->so == rq->accepted_so) break;
n--;mp++;
}
if ( !n ) {
goto notdone; /* not my */
}
} else
goto notdone;
if ( rq->url.host ) /* it have hostpart in url already */
goto notdone;
my_xlog(LOG_HTTP|LOG_DBG, "redir(): transparent: my.\n");
if ( rq->av_pairs)
host = attr_value(rq->av_pairs, "host");
if ( !host ) {
/* We can try to fetch destination using IPF */
#if defined(HAVE_IPF)
struct natlookup natLookup, *natlookupP = &natLookup;
static int natfd = -1, r;
natLookup.nl_inport = rq->my_sa.sin_port;
natLookup.nl_outport = rq->client_sa.sin_port;
natLookup.nl_inip = rq->my_sa.sin_addr;
natLookup.nl_outip = rq->client_sa.sin_addr;
natLookup.nl_flags = IPN_TCP;
if (natfd < 0) {
natfd = open(IPL_NAT, O_RDONLY, 0);
if (natfd < 0) {
my_xlog(LOG_HTTP|LOG_DBG|LOG_SEVERE, "redir(): transparent: NAT open
failed: %m\n");
goto notdone;
}
}
#define NEWSIOCGNATLCMD _IOWR('r', 63, struct natlookup *)
if ( SIOCGNATL == NEWSIOCGNATLCMD)
r = ioctl(natfd, SIOCGNATL, &natLookupP);
else
r = ioctl(natfd, SIOCGNATL, &natLookup);
#undef NEWSIOCGNATLCMD
if ( r < 0 ) {
my_xlog(LOG_HTTP|LOG_DBG|LOG_SEVERE, "redir(): transparent: NAT lookup
failed: ioctl(SIOCGNATL).\n");
goto notdone;
} else {
struct sockaddr_in sa;
bzero(&sa, sizeof(sa));
sa.sin_addr = natLookup.nl_realip;
rq->url.host = my_inet_ntoa(&sa);
rq->url.port = ntohs(natLookup.nl_realport);
goto done;
}
#else
/* last resort - take destination ip from my_sa */
rq->url.host = my_inet_ntoa(&rq->my_sa);
rq->url.port = rq->my_sa.sin_port;
goto notdone;
#endif
}
if ( (dd = strchr(host, ':')) ) {
u_short host_port;
*dd = 0;
host_port = atoi(dd+1);
if ( host_port ) port = host_port;
} else
port = 80;
rq->url.host = strdup(host);
rq->url.port = port;
if ( dd ) *dd = ':';
if ( !TEST(rq->flags, RQ_HAS_HOST) && rq->url.host) {
/* insert Host: header */
put_av_pair(&rq->av_pairs, "Host:", rq->url.host);
}
done:
SET(*flags, MOD_AFLAG_CKACC); /* we must check acces again */
notdone:
UNLOCK_TP_CONFIG ;
return(MOD_CODE_OK);
}