2019-07-28 10:31:56 +08:00
|
|
|
|
2014-11-19 00:25:21 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "lib_acl.h"
|
|
|
|
|
|
|
|
#include "single_proxy.h"
|
|
|
|
|
|
|
|
int var_proxy_log_level;
|
|
|
|
int var_proxy_tmout;
|
|
|
|
int var_proxy_connect_tmout;
|
|
|
|
int var_proxy_rw_tmout;
|
|
|
|
int var_proxy_bufsize;
|
|
|
|
int var_proxy_retries;
|
|
|
|
|
|
|
|
char *var_proxy_banner;
|
|
|
|
char *var_proxy_backend_addr;
|
|
|
|
char *var_proxy_in_file;
|
|
|
|
char *var_proxy_out_file;
|
|
|
|
char *var_proxy_host_allow;
|
|
|
|
|
|
|
|
static ACL_CONFIG_INT_TABLE __conf_int_tab[] = {
|
|
|
|
{ VAR_PROXY_LOG_LEVEL, DEF_PROXY_LOG_LEVEL, &var_proxy_log_level, 0, 0 },
|
|
|
|
{ VAR_PROXY_TMOUT, DEF_PROXY_TMOUT, &var_proxy_tmout, 0, 0 },
|
|
|
|
{ VAR_PROXY_CONNECT_TMOUT, DEF_PROXY_CONNECT_TMOUT, &var_proxy_connect_tmout, 0, 0 },
|
|
|
|
{ VAR_PROXY_RW_TMOUT, DEF_PROXY_RW_TMOUT, &var_proxy_rw_tmout, 0, 0 },
|
|
|
|
{ VAR_PROXY_BUFSIZE, DEF_PROXY_BUFSIZE, &var_proxy_bufsize, 0, 0 },
|
|
|
|
{ VAR_PROXY_RETRIES, DEF_PROXY_RETRIES, &var_proxy_retries, 0, 0},
|
|
|
|
{ 0, 0, 0, 0, 0 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static ACL_CONFIG_STR_TABLE __conf_str_tab[] = {
|
|
|
|
{ VAR_PROXY_BANNER, DEF_PROXY_BANNER, &var_proxy_banner },
|
|
|
|
{ VAR_PROXY_BACKEND_ADDR, DEF_PROXY_BACKEND_ADDR, &var_proxy_backend_addr },
|
|
|
|
{ VAR_PROXY_IN_FILE, DEF_PROXY_IN_FILE, &var_proxy_in_file },
|
|
|
|
{ VAR_PROXY_OUT_FILE, DEF_PROXY_OUT_FILE, &var_proxy_out_file },
|
|
|
|
{ VAR_PROXY_HOST_ALLOW, DEF_PROXY_HOST_ALLOW, &var_proxy_host_allow },
|
|
|
|
{ 0, 0, 0 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static ACL_EVENT *__eventp = NULL;
|
|
|
|
static ACL_VSTREAM *__front_stream = NULL;
|
|
|
|
static ACL_VSTREAM *__backend_stream = NULL;
|
|
|
|
|
|
|
|
static ACL_IPLINK *__host_allow_link = NULL;
|
|
|
|
|
|
|
|
/* forward define */
|
|
|
|
static int __if_host_allow(const char *client_ip);
|
|
|
|
|
|
|
|
static void __proxy_handle_fn(int type acl_unused, ACL_EVENT *event acl_unused,
|
|
|
|
ACL_VSTREAM *stream, void *context)
|
|
|
|
{
|
|
|
|
const char *myname = "__proxy_handle_fn";
|
|
|
|
char buf[8192];
|
|
|
|
int n, ret;
|
|
|
|
|
|
|
|
#undef OVER_RETURN
|
|
|
|
#define OVER_RETURN do { \
|
|
|
|
acl_event_disable_readwrite(__eventp, __backend_stream); \
|
|
|
|
acl_vstream_close(__backend_stream); \
|
|
|
|
__backend_stream = NULL; \
|
|
|
|
return; \
|
|
|
|
} while (0);
|
|
|
|
|
|
|
|
if (context == NULL) {
|
|
|
|
acl_msg_error("%s(%d)->%s: input error, null context",
|
|
|
|
__FILE__, __LINE__, myname);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stream == __front_stream) {
|
|
|
|
n = acl_vstream_read(stream, buf, sizeof(buf) - 1);
|
|
|
|
if (n == ACL_VSTREAM_EOF) {
|
|
|
|
if(var_proxy_log_level > 3)
|
|
|
|
acl_msg_info("%s(%d)->%s: read over",
|
|
|
|
__FILE__, __LINE__, myname);
|
|
|
|
OVER_RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = acl_vstream_writen(__backend_stream, buf, n);
|
|
|
|
if (ret != n) {
|
|
|
|
if(var_proxy_log_level > 3)
|
|
|
|
acl_msg_info("%s(%d)->%s: write error = %s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
strerror(errno));
|
|
|
|
OVER_RETURN;
|
|
|
|
}
|
|
|
|
} else if (stream == __backend_stream) {
|
|
|
|
n = acl_vstream_read(stream, buf, sizeof(buf) - 1);
|
|
|
|
if (n == ACL_VSTREAM_EOF) {
|
|
|
|
if(var_proxy_log_level > 3)
|
|
|
|
acl_msg_info("%s(%d)->%s: read over",
|
|
|
|
__FILE__, __LINE__, myname);
|
|
|
|
OVER_RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = acl_vstream_writen(__front_stream, buf, n);
|
|
|
|
if (ret != n) {
|
|
|
|
if(var_proxy_log_level > 3)
|
|
|
|
acl_msg_info("%s(%d)->%s: write error = %s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
strerror(errno));
|
|
|
|
OVER_RETURN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-05 00:01:22 +08:00
|
|
|
static void __service(void *ctx acl_unused, ACL_VSTREAM *stream)
|
2014-11-19 00:25:21 +08:00
|
|
|
{
|
|
|
|
const char *myname = "__service";
|
|
|
|
char buf[64];
|
|
|
|
int connect_retries = var_proxy_retries;
|
|
|
|
|
|
|
|
__front_stream = stream;
|
|
|
|
|
|
|
|
if (var_proxy_log_level > 3)
|
2017-07-05 00:01:22 +08:00
|
|
|
acl_msg_info("%s(%d)->%s: rw_timeout = %d",
|
|
|
|
__FILE__, __LINE__, myname, stream->rw_timeout);
|
2014-11-19 00:25:21 +08:00
|
|
|
|
|
|
|
(void) acl_getpeername(ACL_VSTREAM_SOCK(__front_stream),
|
|
|
|
buf, sizeof(buf));
|
|
|
|
acl_vstream_set_peer(__front_stream, buf);
|
|
|
|
|
|
|
|
if (__if_host_allow(buf) < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (var_proxy_log_level > 2)
|
|
|
|
acl_msg_info("%s(%d)->%s: connected from addr=%s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
ACL_VSTREAM_PEER(__front_stream));
|
|
|
|
|
|
|
|
while (connect_retries) {
|
|
|
|
__backend_stream =
|
|
|
|
acl_vstream_connect(var_proxy_backend_addr,
|
|
|
|
ACL_BLOCKING,
|
|
|
|
var_proxy_connect_tmout,
|
|
|
|
var_proxy_rw_tmout,
|
|
|
|
var_proxy_bufsize);
|
|
|
|
if (__backend_stream != NULL)
|
|
|
|
break;
|
|
|
|
|
|
|
|
acl_msg_warn("%s(%d)->%s: can't connect server = %s,"
|
|
|
|
" serr = %s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
var_proxy_backend_addr, strerror(errno));
|
|
|
|
connect_retries--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (__backend_stream == NULL) {
|
|
|
|
acl_msg_error("%s(%d)->%s: can't connect server=%s, retries=%d",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
var_proxy_backend_addr, var_proxy_retries);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (var_proxy_log_level > 2)
|
|
|
|
acl_msg_info("%s(%d)->%s: ok, connect ip=%s, retries=%d",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
ACL_VSTREAM_PEER(__backend_stream),
|
|
|
|
var_proxy_retries - connect_retries);
|
|
|
|
|
|
|
|
acl_event_enable_read(__eventp,
|
|
|
|
__front_stream,
|
|
|
|
0,
|
|
|
|
__proxy_handle_fn,
|
|
|
|
__front_stream);
|
|
|
|
acl_event_enable_read(__eventp,
|
|
|
|
__backend_stream,
|
|
|
|
0,
|
|
|
|
__proxy_handle_fn,
|
|
|
|
__backend_stream);
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
acl_watchdog_pat();
|
|
|
|
acl_event_loop(__eventp);
|
|
|
|
if (__backend_stream == NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
acl_event_disable_readwrite(__eventp, __front_stream);
|
|
|
|
__front_stream = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __add_one_host_item(ACL_IPLINK *allow_link, const char *pitem)
|
|
|
|
{
|
|
|
|
char myname[] = "__add_one_host_item";
|
|
|
|
char *pdata = NULL;
|
|
|
|
char *from, *to, *ptr;
|
|
|
|
|
|
|
|
#undef RETURN
|
|
|
|
#define RETURN do { \
|
|
|
|
if (pdata != NULL) \
|
|
|
|
acl_myfree(pdata); \
|
|
|
|
return; \
|
|
|
|
} while (0);
|
|
|
|
|
|
|
|
if (pitem == NULL || *pitem == 0) {
|
|
|
|
acl_msg_error("%s(%d)->%s: pitem invalid",
|
|
|
|
__FILE__, __LINE__, myname);
|
|
|
|
RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
pdata = acl_mystrdup(pitem);
|
|
|
|
|
|
|
|
from = pdata;
|
|
|
|
|
|
|
|
/* skip when: '[' || ',' || ' ' || '\t' */
|
|
|
|
while (*from == '[' || *from == ',' || *from == ' ' || *from == '\t')
|
|
|
|
from++;
|
|
|
|
if (*from == 0) {
|
|
|
|
acl_msg_error("%s(%d)->%s: invalid item: %s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
pitem);
|
|
|
|
RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = from;
|
|
|
|
/* the "from" end with: ' ' || '\t' || ',' */
|
|
|
|
while (*ptr) {
|
|
|
|
if (*ptr == ' ' || *ptr == '\t' || *ptr == ',') {
|
|
|
|
*ptr++ = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
if (*from == 0) {
|
|
|
|
acl_msg_error("%s(%d)->%s: invalid item: %s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
pitem);
|
|
|
|
RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* skip when: ' ' || '\t' || ',' */
|
|
|
|
while (*ptr == ' ' || *ptr == '\t' || *ptr == ',')
|
|
|
|
ptr++;
|
|
|
|
if (*ptr == 0) {
|
|
|
|
acl_msg_error("%s(%d)->%s: invalid item: %s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
pitem);
|
|
|
|
RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
to = ptr;
|
|
|
|
/* the "to" end with: ' ' || '\t' || ',' || ']' */
|
|
|
|
while (*ptr) {
|
|
|
|
if (*ptr == ' ' || *ptr == '\t' || *ptr == ',' || *ptr == ']') {
|
|
|
|
*ptr = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
if (*to == 0) {
|
|
|
|
acl_msg_error("%s(%d)->%s: invalid item: %s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
pitem);
|
|
|
|
RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (acl_iplink_insert(allow_link, from, to) == NULL) {
|
|
|
|
acl_msg_error("%s(%d)->%s: call acl_iplink_insert error,"
|
|
|
|
" invalid item: %s",
|
|
|
|
__FILE__, __LINE__, myname, pitem);
|
|
|
|
RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* else: OK */
|
|
|
|
if (var_proxy_log_level > 1)
|
|
|
|
acl_msg_info("%s(%d)->%s: from=%s, to=%s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
from, to);
|
|
|
|
RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __add_host_allow(const char *host_allow)
|
|
|
|
{
|
|
|
|
char myname[] = "__add_host_allow";
|
|
|
|
char *pdata, *ptr, *pitem;
|
|
|
|
|
|
|
|
if (host_allow == NULL)
|
|
|
|
host_allow = DEF_PROXY_HOST_ALLOW;
|
|
|
|
|
|
|
|
pdata = acl_mystrdup(host_allow);
|
|
|
|
if (pdata == NULL)
|
|
|
|
acl_msg_fatal("%s(%d)->%s: call acl_mystrdup error=%s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
strerror(errno));
|
|
|
|
|
|
|
|
__host_allow_link = acl_iplink_create(10);
|
|
|
|
if (__host_allow_link == NULL)
|
|
|
|
acl_msg_fatal("%s(%d)->%s: call acl_iplink_create error=%s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
strerror(errno));
|
|
|
|
ptr = pdata;
|
|
|
|
while (1) {
|
|
|
|
pitem = acl_mystrtok(&ptr, "]");
|
|
|
|
if (pitem == NULL)
|
|
|
|
break;
|
|
|
|
__add_one_host_item(__host_allow_link, pitem);
|
|
|
|
}
|
|
|
|
|
|
|
|
acl_myfree(pdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __if_host_allow(const char *client_ip)
|
|
|
|
{
|
|
|
|
char myname[] = "__if_host_allow";
|
|
|
|
|
|
|
|
if (client_ip == NULL || *client_ip == 0) {
|
|
|
|
acl_msg_info("%s(%d)->%s: invalid input",
|
|
|
|
__FILE__, __LINE__, myname);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (__host_allow_link == NULL) {
|
|
|
|
if (var_proxy_log_level > 3)
|
|
|
|
acl_msg_info("%s(%d)->%s: host allow, ip=%s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
client_ip);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (acl_iplink_lookup_str(__host_allow_link, client_ip) != NULL) {
|
|
|
|
if (var_proxy_log_level > 3)
|
|
|
|
acl_msg_info("%s(%d)->%s: host allow, ip=%s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
client_ip);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (var_proxy_log_level > 3)
|
|
|
|
acl_msg_warn("%s(%d)->%s: host deny, ip = %s",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
client_ip);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
2015-01-04 22:51:01 +08:00
|
|
|
static void __pre_jail_init(char *name acl_unused, char **argv acl_unused)
|
2014-11-19 00:25:21 +08:00
|
|
|
{
|
|
|
|
char myname[] = "__pre_jail_init";
|
|
|
|
|
|
|
|
acl_msg_info("%s(%d)->%s: var_proxy_log_level=%d",
|
|
|
|
__FILE__, __LINE__, myname, var_proxy_log_level);
|
|
|
|
|
|
|
|
acl_msg_info("host-allow:[%s]", var_proxy_host_allow); /* zsx test */
|
|
|
|
__add_host_allow(var_proxy_host_allow);
|
|
|
|
|
|
|
|
if (var_proxy_log_level > 3)
|
|
|
|
acl_msg_info("%s(%d)->%s: test only",
|
|
|
|
__FILE__, __LINE__, myname);
|
|
|
|
if (var_proxy_retries <= 0) {
|
|
|
|
acl_msg_warn("%s(%d)->%s: proxy_tetries = %d, use default=%d",
|
|
|
|
__FILE__, __LINE__, myname,
|
|
|
|
var_proxy_retries, DEF_PROXY_RETRIES);
|
|
|
|
var_proxy_retries = DEF_PROXY_RETRIES;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (var_proxy_backend_addr == NULL
|
|
|
|
|| strcmp(var_proxy_backend_addr, DEF_PROXY_BACKEND_ADDR) == 0) {
|
|
|
|
acl_msg_fatal("%s(%d)->%s: proxy_backend_addr invalid",
|
|
|
|
__FILE__, __LINE__, myname);
|
|
|
|
}
|
|
|
|
|
|
|
|
__eventp = acl_event_new_select(acl_var_single_delay_sec,
|
|
|
|
acl_var_single_delay_usec);
|
|
|
|
if (__eventp == NULL)
|
|
|
|
acl_msg_fatal("%s(%d)->%s: acl_event_new error",
|
|
|
|
__FILE__, __LINE__, myname);
|
|
|
|
}
|
|
|
|
|
2015-01-04 22:51:01 +08:00
|
|
|
static void __post_jail_init(char *name acl_unused, char **argv acl_unused)
|
2014-11-19 00:25:21 +08:00
|
|
|
{
|
|
|
|
char myname[] = "__post_jail_init";
|
|
|
|
|
|
|
|
if (var_proxy_log_level > 3)
|
|
|
|
acl_msg_info("%s(%d)->%s: test only",
|
|
|
|
__FILE__, __LINE__, myname);
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
acl_msg_info("%s: start...", __FILE__);
|
|
|
|
printf("%s: starting...", __FILE__);
|
|
|
|
|
|
|
|
acl_single_server_main(argc, argv, __service,
|
|
|
|
ACL_MASTER_SERVER_INT_TABLE, __conf_int_tab,
|
|
|
|
ACL_MASTER_SERVER_STR_TABLE, __conf_str_tab,
|
|
|
|
ACL_MASTER_SERVER_PRE_INIT, __pre_jail_init,
|
|
|
|
ACL_MASTER_SERVER_POST_INIT, __post_jail_init,
|
|
|
|
0);
|
|
|
|
exit (0);
|
|
|
|
}
|
|
|
|
|