tpws: ipcache

This commit is contained in:
bol-van 2025-05-04 10:42:47 +03:00
parent c626d88f54
commit 9629ce5cb7
7 changed files with 432 additions and 13 deletions

View File

@ -550,7 +550,7 @@ struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, co
if (data) memcpy(entry->data,data,size); if (data) memcpy(entry->data,data,size);
entry->size = size; entry->size = size;
entry->size_buf = size+size_reserve; entry->size_buf = size+size_reserve;
// insert to the end // insert to the end
struct blob_item *itemc,*iteml=LIST_FIRST(head); struct blob_item *itemc,*iteml=LIST_FIRST(head);
if (iteml) if (iteml)

View File

@ -20,6 +20,8 @@
#define FIX_SEG_DEFAULT_MAX_WAIT 50 #define FIX_SEG_DEFAULT_MAX_WAIT 50
#define IPCACHE_LIFETIME 7200
enum bindll { unwanted=0, no, prefer, force }; enum bindll { unwanted=0, no, prefer, force };
#define MAX_BINDS 32 #define MAX_BINDS 32
@ -140,6 +142,10 @@ struct params_s
bool tamper; // any tamper option is set bool tamper; // any tamper option is set
bool tamper_lim; // tamper-start or tamper-cutoff set in any profile bool tamper_lim; // tamper-start or tamper-cutoff set in any profile
struct desync_profile_list_head desync_profiles; struct desync_profile_list_head desync_profiles;
unsigned int ipcache_lifetime;
bool cache_hostname;
ip_cache ipcache;
}; };
extern struct params_s params; extern struct params_s params;

View File

@ -3,6 +3,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <arpa/inet.h>
#define DESTROY_STR_POOL(etype, ppool) \ #define DESTROY_STR_POOL(etype, ppool) \
etype *elem, *tmp; \ etype *elem, *tmp; \
@ -517,3 +518,277 @@ bool port_filters_deny_if_empty(struct port_filters_head *head)
if (LIST_FIRST(head)) return true; if (LIST_FIRST(head)) return true;
return pf_parse("0",&pf) && port_filter_add(head,&pf); return pf_parse("0",&pf) && port_filter_add(head,&pf);
} }
struct blob_item *blob_collection_add(struct blob_collection_head *head)
{
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
if (entry)
{
// insert to the end
struct blob_item *itemc,*iteml=LIST_FIRST(head);
if (iteml)
{
while ((itemc=LIST_NEXT(iteml,next))) iteml = itemc;
LIST_INSERT_AFTER(iteml, entry, next);
}
else
LIST_INSERT_HEAD(head, entry, next);
}
return entry;
}
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve)
{
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
if (!entry) return NULL;
if (!(entry->data = malloc(size+size_reserve)))
{
free(entry);
return NULL;
}
if (data) memcpy(entry->data,data,size);
entry->size = size;
entry->size_buf = size+size_reserve;
// insert to the end
struct blob_item *itemc,*iteml=LIST_FIRST(head);
if (iteml)
{
while ((itemc=LIST_NEXT(iteml,next))) iteml = itemc;
LIST_INSERT_AFTER(iteml, entry, next);
}
else
LIST_INSERT_HEAD(head, entry, next);
return entry;
}
void blob_collection_destroy(struct blob_collection_head *head)
{
struct blob_item *entry;
while ((entry = LIST_FIRST(head)))
{
LIST_REMOVE(entry, next);
free(entry->extra);
free(entry->extra2);
free(entry->data);
free(entry);
}
}
bool blob_collection_empty(const struct blob_collection_head *head)
{
return !LIST_FIRST(head);
}
static void ipcache_item_touch(ip_cache_item *item)
{
time(&item->last);
}
static void ipcache_item_init(ip_cache_item *item)
{
ipcache_item_touch(item);
item->hostname = NULL;
}
static void ipcache_item_destroy(ip_cache_item *item)
{
free(item->hostname);
}
static void ipcache4Destroy(ip_cache4 **ipcache)
{
ip_cache4 *elem, *tmp;
HASH_ITER(hh, *ipcache, elem, tmp)
{
HASH_DEL(*ipcache, elem);
ipcache_item_destroy(&elem->data);
free(elem);
}
}
static void ipcache4Key(ip4if *key, const struct in_addr *a)
{
memset(key,0,sizeof(*key)); // make sure everything is zero
key->addr = *a;
}
static ip_cache4 *ipcache4Find(ip_cache4 *ipcache, const struct in_addr *a)
{
ip_cache4 *entry;
struct ip4if key;
ipcache4Key(&key,a);
HASH_FIND(hh, ipcache, &key, sizeof(key), entry);
return entry;
}
static ip_cache4 *ipcache4Add(ip_cache4 **ipcache, const struct in_addr *a)
{
// avoid dups
ip_cache4 *entry = ipcache4Find(*ipcache,a);
if (entry) return entry; // already included
entry = malloc(sizeof(ip_cache4));
if (!entry) return NULL;
ipcache4Key(&entry->key,a);
oom = false;
HASH_ADD(hh, *ipcache, key, sizeof(entry->key), entry);
if (oom) { free(entry); return NULL; }
ipcache_item_init(&entry->data);
return entry;
}
static void ipcache4Print(ip_cache4 *ipcache)
{
char s_ip[16];
time_t now;
ip_cache4 *ipc, *tmp;
time(&now);
HASH_ITER(hh, ipcache , ipc, tmp)
{
*s_ip=0;
inet_ntop(AF_INET, &ipc->key.addr, s_ip, sizeof(s_ip));
printf("%s : hostname=%s now=last+%llu\n", s_ip, ipc->data.hostname ? ipc->data.hostname : "", (unsigned long long)(now-ipc->data.last));
}
}
static void ipcache6Destroy(ip_cache6 **ipcache)
{
ip_cache6 *elem, *tmp;
HASH_ITER(hh, *ipcache, elem, tmp)
{
HASH_DEL(*ipcache, elem);
ipcache_item_destroy(&elem->data);
free(elem);
}
}
static void ipcache6Key(ip6if *key, const struct in6_addr *a)
{
memset(key,0,sizeof(*key)); // make sure everything is zero
key->addr = *a;
}
static ip_cache6 *ipcache6Find(ip_cache6 *ipcache, const struct in6_addr *a)
{
ip_cache6 *entry;
ip6if key;
ipcache6Key(&key,a);
HASH_FIND(hh, ipcache, &key, sizeof(key), entry);
return entry;
}
static ip_cache6 *ipcache6Add(ip_cache6 **ipcache, const struct in6_addr *a)
{
// avoid dups
ip_cache6 *entry = ipcache6Find(*ipcache,a);
if (entry) return entry; // already included
entry = malloc(sizeof(ip_cache6));
if (!entry) return NULL;
ipcache6Key(&entry->key,a);
oom = false;
HASH_ADD(hh, *ipcache, key, sizeof(entry->key), entry);
if (oom) { free(entry); return NULL; }
ipcache_item_init(&entry->data);
return entry;
}
static void ipcache6Print(ip_cache6 *ipcache)
{
char s_ip[40];
time_t now;
ip_cache6 *ipc, *tmp;
time(&now);
HASH_ITER(hh, ipcache , ipc, tmp)
{
*s_ip=0;
inet_ntop(AF_INET6, &ipc->key.addr, s_ip, sizeof(s_ip));
printf("%s : hostname=%s now=last+%llu\n", s_ip, ipc->data.hostname ? ipc->data.hostname : "", (unsigned long long)(now-ipc->data.last));
}
}
void ipcacheDestroy(ip_cache *ipcache)
{
ipcache4Destroy(&ipcache->ipcache4);
ipcache6Destroy(&ipcache->ipcache6);
}
void ipcachePrint(ip_cache *ipcache)
{
ipcache4Print(ipcache->ipcache4);
ipcache6Print(ipcache->ipcache6);
}
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6)
{
ip_cache4 *ipcache4;
ip_cache6 *ipcache6;
if (a4)
{
if ((ipcache4 = ipcache4Add(&ipcache->ipcache4,a4)))
{
ipcache_item_touch(&ipcache4->data);
return &ipcache4->data;
}
}
else if (a6)
{
if ((ipcache6 = ipcache6Add(&ipcache->ipcache6,a6)))
{
ipcache_item_touch(&ipcache6->data);
return &ipcache6->data;
}
}
return NULL;
}
static void ipcache4_purge(ip_cache4 **ipcache, time_t lifetime)
{
ip_cache4 *elem, *tmp;
time_t now = time(NULL);
HASH_ITER(hh, *ipcache, elem, tmp)
{
if (now >= (elem->data.last + lifetime))
{
HASH_DEL(*ipcache, elem);
ipcache_item_destroy(&elem->data);
free(elem);
}
}
}
static void ipcache6_purge(ip_cache6 **ipcache, time_t lifetime)
{
ip_cache6 *elem, *tmp;
time_t now = time(NULL);
HASH_ITER(hh, *ipcache, elem, tmp)
{
if (now >= (elem->data.last + lifetime))
{
HASH_DEL(*ipcache, elem);
ipcache_item_destroy(&elem->data);
free(elem);
}
}
}
static void ipcache_purge(ip_cache *ipcache, time_t lifetime)
{
if (lifetime) // 0 = no expire
{
ipcache4_purge(&ipcache->ipcache4, lifetime);
ipcache6_purge(&ipcache->ipcache6, lifetime);
}
}
static time_t ipcache_purge_prev=0;
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime)
{
time_t now = time(NULL);
// do not purge too often to save resources
if (ipcache_purge_prev != now)
{
ipcache_purge(ipcache, lifetime);
ipcache_purge_prev = now;
}
}

View File

@ -3,6 +3,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <ctype.h> #include <ctype.h>
#include <sys/queue.h> #include <sys/queue.h>
#include <net/if.h>
#include <time.h> #include <time.h>
#include "helpers.h" #include "helpers.h"
@ -146,3 +147,55 @@ bool port_filter_add(struct port_filters_head *head, const port_filter *pf);
void port_filters_destroy(struct port_filters_head *head); void port_filters_destroy(struct port_filters_head *head);
bool port_filters_in_range(const struct port_filters_head *head, uint16_t port); bool port_filters_in_range(const struct port_filters_head *head, uint16_t port);
bool port_filters_deny_if_empty(struct port_filters_head *head); bool port_filters_deny_if_empty(struct port_filters_head *head);
struct blob_item {
uint8_t *data; // main data blob
size_t size; // main data blob size
size_t size_buf;// main data blob allocated size
void *extra; // any data without size
void *extra2; // any data without size
LIST_ENTRY(blob_item) next;
};
LIST_HEAD(blob_collection_head, blob_item);
struct blob_item *blob_collection_add(struct blob_collection_head *head);
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve);
void blob_collection_destroy(struct blob_collection_head *head);
bool blob_collection_empty(const struct blob_collection_head *head);
typedef struct ip4if
{
struct in_addr addr;
} ip4if;
typedef struct ip6if
{
struct in6_addr addr;
} ip6if;
typedef struct ip_cache_item
{
time_t last;
char *hostname;
} ip_cache_item;
typedef struct ip_cache4
{
ip4if key;
ip_cache_item data;
UT_hash_handle hh; /* makes this structure hashable */
} ip_cache4;
typedef struct ip_cache6
{
ip6if key;
ip_cache_item data;
UT_hash_handle hh; /* makes this structure hashable */
} ip_cache6;
typedef struct ip_cache
{
ip_cache4 *ipcache4;
ip_cache6 *ipcache6;
} ip_cache;
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6);
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime);
void ipcacheDestroy(ip_cache *ipcache);
void ipcachePrint(ip_cache *ipcache);

View File

@ -7,6 +7,7 @@
#include "ipset.h" #include "ipset.h"
#include "protocol.h" #include "protocol.h"
#include "helpers.h" #include "helpers.h"
#include "pools.h"
#define PKTDATA_MAXDUMP 32 #define PKTDATA_MAXDUMP 32
@ -90,6 +91,48 @@ static void TLSDebug(const uint8_t *tls,size_t sz)
TLSDebugHandshake(tls+5,sz-5); TLSDebugHandshake(tls+5,sz-5);
} }
static bool ipcache_put_hostname(const struct in_addr *a4, const struct in6_addr *a6, const char *hostname)
{
if (!params.cache_hostname) return true;
ip_cache_item *ipc = ipcacheTouch(&params.ipcache,a4,a6);
if (!ipc)
{
DLOG_ERR("ipcache_put_hostname: out of memory\n");
return false;
}
free(ipc->hostname);
if (!(ipc->hostname = strdup(hostname)))
{
DLOG_ERR("ipcache_put_hostname: out of memory\n");
return false;
}
VPRINT("hostname cached: %s\n", hostname);
return true;
}
static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr *a6, char *hostname, size_t hostname_buf_len)
{
if (!params.cache_hostname)
{
*hostname = 0;
return true;
}
ip_cache_item *ipc = ipcacheTouch(&params.ipcache,a4,a6);
if (!ipc)
{
DLOG_ERR("ipcache_get_hostname: out of memory\n");
return false;
}
if (ipc->hostname)
{
VPRINT("got cached hostname: %s\n", ipc->hostname);
snprintf(hostname,hostname_buf_len,"%s",ipc->hostname);
}
else
*hostname = 0;
return true;
}
static bool dp_match(struct desync_profile *dp, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto) static bool dp_match(struct desync_profile *dp, const struct sockaddr *dest, const char *hostname, t_l7proto l7proto)
{ {
bool bHostlistsEmpty; bool bHostlistsEmpty;
@ -145,8 +188,17 @@ static struct desync_profile *dp_find(struct desync_profile_list_head *head, con
VPRINT("desync profile not found\n"); VPRINT("desync profile not found\n");
return NULL; return NULL;
} }
void apply_desync_profile(t_ctrack *ctrack, const struct sockaddr *dest) void apply_desync_profile(t_ctrack *ctrack, const struct sockaddr *dest)
{ {
ipcachePurgeRateLimited(&params.ipcache, params.ipcache_lifetime);
if (!ctrack->hostname)
{
char host[256];
if (ipcache_get_hostname(dest->sa_family==AF_INET ? &((struct sockaddr_in*)dest)->sin_addr : NULL, dest->sa_family==AF_INET6 ? &((struct sockaddr_in6*)dest)->sin6_addr : NULL , host, sizeof(host)) && *host)
if (!(ctrack->hostname=strdup(host)))
DLOG_ERR("hostname dup : out of memory");
}
ctrack->dp = dp_find(&params.desync_profiles, dest, ctrack->hostname, ctrack->l7proto); ctrack->dp = dp_find(&params.desync_profiles, dest, ctrack->hostname, ctrack->l7proto);
} }
@ -215,7 +267,11 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
} }
if (bHaveHost) if (bHaveHost)
{
VPRINT("request hostname: %s\n", Host); VPRINT("request hostname: %s\n", Host);
if (!ipcache_put_hostname(dest->sa_family==AF_INET ? &((struct sockaddr_in*)dest)->sin_addr : NULL, dest->sa_family==AF_INET6 ? &((struct sockaddr_in6*)dest)->sin6_addr : NULL , Host))
DLOG_ERR("ipcache_put_hostname: out of memory");
}
bool bDiscoveredL7 = ctrack->l7proto==UNKNOWN && l7proto!=UNKNOWN; bool bDiscoveredL7 = ctrack->l7proto==UNKNOWN && l7proto!=UNKNOWN;
if (bDiscoveredL7) if (bDiscoveredL7)
@ -224,15 +280,17 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
ctrack->l7proto=l7proto; ctrack->l7proto=l7proto;
} }
bool bDiscoveredHostname = bHaveHost && !ctrack->hostname; bool bDiscoveredHostname = bHaveHost && !ctrack->hostname_discovered;
if (bDiscoveredHostname) if (bDiscoveredHostname)
{ {
VPRINT("discovered hostname\n"); VPRINT("discovered hostname\n");
free(ctrack->hostname);
if (!(ctrack->hostname=strdup(Host))) if (!(ctrack->hostname=strdup(Host)))
{ {
DLOG_ERR("strdup hostname : out of memory\n"); DLOG_ERR("strdup hostname : out of memory\n");
return; return;
} }
ctrack->hostname_discovered = true;
} }
if (bDiscoveredL7 || bDiscoveredHostname) if (bDiscoveredL7 || bDiscoveredHostname)

View File

@ -15,6 +15,7 @@ typedef struct
t_l7proto l7proto; t_l7proto l7proto;
bool bTamperInCutoff; bool bTamperInCutoff;
bool b_host_checked,b_host_matches,b_ah_check; bool b_host_checked,b_host_matches,b_ah_check;
bool hostname_discovered;
char *hostname; char *hostname;
struct desync_profile *dp; // desync profile cache struct desync_profile *dp; // desync profile cache
} t_ctrack; } t_ctrack;

View File

@ -88,6 +88,12 @@ static void onusr2(int sig)
HostFailPoolDump(dpl->dp.hostlist_auto_fail_counters); HostFailPoolDump(dpl->dp.hostlist_auto_fail_counters);
} }
if (params.cache_hostname)
{
printf("\nIPCACHE\n");
ipcachePrint(&params.ipcache);
}
printf("\n"); printf("\n");
} }
@ -215,6 +221,8 @@ static void exithelp(void)
#if defined(__linux__) #if defined(__linux__)
" --fix-seg=<int>\t\t\t; fix segmentation failures at the cost of possible slowdown. wait up to N msec (default %u)\n" " --fix-seg=<int>\t\t\t; fix segmentation failures at the cost of possible slowdown. wait up to N msec (default %u)\n"
#endif #endif
" --ipcache-lifetime=<int>\t\t; time in seconds to keep cached domain name (default %u). 0 = no expiration\n"
" --ipcache-hostname=[0|1]\t\t; 1 or no argument enables ip->hostname caching\n"
" --debug=0|1|2|syslog|@<filename>\t; 1 and 2 means log to console and set debug level. for other targets use --debug-level.\n" " --debug=0|1|2|syslog|@<filename>\t; 1 and 2 means log to console and set debug level. for other targets use --debug-level.\n"
" --debug-level=0|1|2\t\t\t; specify debug level\n" " --debug-level=0|1|2\t\t\t; specify debug level\n"
" --dry-run\t\t\t\t; verify parameters and exit with code 0 if successful\n" " --dry-run\t\t\t\t; verify parameters and exit with code 0 if successful\n"
@ -272,6 +280,7 @@ static void exithelp(void)
#ifdef __linux__ #ifdef __linux__
FIX_SEG_DEFAULT_MAX_WAIT, FIX_SEG_DEFAULT_MAX_WAIT,
#endif #endif
IPCACHE_LIFETIME,
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT
); );
exit(1); exit(1);
@ -292,6 +301,7 @@ static void cleanup_params(void)
hostlist_files_destroy(&params.hostlists); hostlist_files_destroy(&params.hostlists);
ipset_files_destroy(&params.ipsets); ipset_files_destroy(&params.ipsets);
ipcacheDestroy(&params.ipcache);
} }
static void exithelp_clean(void) static void exithelp_clean(void)
{ {
@ -628,6 +638,8 @@ enum opt_indices {
IDX_MAXCONN, IDX_MAXCONN,
IDX_MAXFILES, IDX_MAXFILES,
IDX_MAX_ORPHAN_TIME, IDX_MAX_ORPHAN_TIME,
IDX_IPCACHE_LIFETIME,
IDX_IPCACHE_HOSTNAME,
IDX_HOSTCASE, IDX_HOSTCASE,
IDX_HOSTSPELL, IDX_HOSTSPELL,
IDX_HOSTDOT, IDX_HOSTDOT,
@ -718,6 +730,8 @@ static const struct option long_options[] = {
[IDX_UID] = {"uid", required_argument, 0, 0}, [IDX_UID] = {"uid", required_argument, 0, 0},
[IDX_MAXCONN] = {"maxconn", required_argument, 0, 0}, [IDX_MAXCONN] = {"maxconn", required_argument, 0, 0},
[IDX_MAXFILES] = {"maxfiles", required_argument, 0, 0}, [IDX_MAXFILES] = {"maxfiles", required_argument, 0, 0},
[IDX_IPCACHE_LIFETIME] = {"ipcache-lifetime", required_argument, 0, 0},
[IDX_IPCACHE_HOSTNAME] = {"ipcache-hostname", optional_argument, 0, 0},
[IDX_MAX_ORPHAN_TIME] = {"max-orphan-time", required_argument, 0, 0}, [IDX_MAX_ORPHAN_TIME] = {"max-orphan-time", required_argument, 0, 0},
[IDX_HOSTCASE] = {"hostcase", no_argument, 0, 0}, [IDX_HOSTCASE] = {"hostcase", no_argument, 0, 0},
[IDX_HOSTSPELL] = {"hostspell", required_argument, 0, 0}, [IDX_HOSTSPELL] = {"hostspell", required_argument, 0, 0},
@ -804,6 +818,7 @@ void parse_params(int argc, char *argv[])
params.maxconn = DEFAULT_MAX_CONN; params.maxconn = DEFAULT_MAX_CONN;
params.max_orphan_time = DEFAULT_MAX_ORPHAN_TIME; params.max_orphan_time = DEFAULT_MAX_ORPHAN_TIME;
params.binds_last = -1; params.binds_last = -1;
params.ipcache_lifetime = IPCACHE_LIFETIME;
#if defined(__linux__) || defined(__APPLE__) #if defined(__linux__) || defined(__APPLE__)
params.tcp_user_timeout_local = DEFAULT_TCP_USER_TIMEOUT_LOCAL; params.tcp_user_timeout_local = DEFAULT_TCP_USER_TIMEOUT_LOCAL;
params.tcp_user_timeout_remote = DEFAULT_TCP_USER_TIMEOUT_REMOTE; params.tcp_user_timeout_remote = DEFAULT_TCP_USER_TIMEOUT_REMOTE;
@ -976,6 +991,16 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_IPCACHE_LIFETIME:
if (sscanf(optarg, "%u", &params.ipcache_lifetime)!=1)
{
DLOG_ERR("invalid ipcache-lifetime value\n");
exit_clean(1);
}
break;
case IDX_IPCACHE_HOSTNAME:
params.cache_hostname = !optarg || !!atoi(optarg);
break;
case IDX_HOSTCASE: case IDX_HOSTCASE:
dp->hostcase = true; dp->hostcase = true;
params.tamper = true; params.tamper = true;
@ -1815,14 +1840,6 @@ int main(int argc, char *argv[])
parse_params(argc, argv); parse_params(argc, argv);
argv=NULL; argc=0; argv=NULL; argc=0;
if (params.daemon) daemonize();
if (*params.pidfile && !writepid(params.pidfile))
{
DLOG_ERR("could not write pidfile\n");
goto exiterr;
}
memset(&list, 0, sizeof(list)); memset(&list, 0, sizeof(list));
for(i=0;i<=params.binds_last;i++) listen_fd[i]=-1; for(i=0;i<=params.binds_last;i++) listen_fd[i]=-1;
@ -2054,6 +2071,18 @@ int main(int argc, char *argv[])
} }
} }
if (params.cache_hostname) VPRINT("ipcache lifetime %us\n", params.ipcache_lifetime);
DLOG_CONDUP(params.proxy_type==CONN_TYPE_SOCKS ? "socks mode\n" : "transparent proxy mode\n");
if (!params.tamper) DLOG_CONDUP("TCP proxy mode (no tampering)\n");
if (params.daemon) daemonize();
if (*params.pidfile && !writepid(params.pidfile))
{
DLOG_ERR("could not write pidfile\n");
goto exiterr;
}
set_ulimit(); set_ulimit();
sec_harden(); sec_harden();
if (params.droproot && !droproot(params.uid,params.gid)) if (params.droproot && !droproot(params.uid,params.gid))
@ -2074,9 +2103,6 @@ int main(int argc, char *argv[])
goto exiterr; goto exiterr;
} }
DLOG_CONDUP(params.proxy_type==CONN_TYPE_SOCKS ? "socks mode\n" : "transparent proxy mode\n");
if (!params.tamper) DLOG_CONDUP("TCP proxy mode (no tampering)\n");
signal(SIGHUP, onhup); signal(SIGHUP, onhup);
signal(SIGUSR2, onusr2); signal(SIGUSR2, onusr2);