mirror of
https://github.com/hufrea/byedpi.git
synced 2024-11-24 07:45:32 +03:00
Transparent proxy mode (#114)
* Transparent proxy * Typo errors * long long -> intmax_t for printing time_t --------- Co-authored-by: vel21ripn <> Co-authored-by: Konstantin Saliy <ksaliy@s-terra.ru>
This commit is contained in:
parent
1d6c0a132e
commit
02a9e046fd
4 changed files with 67 additions and 6 deletions
2
extend.c
2
extend.c
|
@ -85,7 +85,7 @@ int mode_add_get(struct sockaddr_ina *dst, int m)
|
|||
}
|
||||
time(&t);
|
||||
if (t > val->time + params.cache_ttl) {
|
||||
LOG(LOG_S, "time=%ld, now=%ld, ignore\n", val->time, t);
|
||||
LOG(LOG_S, "time=%jd, now=%jd, ignore\n", (intmax_t)val->time, (intmax_t)t);
|
||||
return 0;
|
||||
}
|
||||
return val->m;
|
||||
|
|
12
main.c
12
main.c
|
@ -61,6 +61,9 @@ struct params params = {
|
|||
const char help_text[] = {
|
||||
" -i, --ip, <ip> Listening IP, default 0.0.0.0\n"
|
||||
" -p, --port <num> Listening port, default 1080\n"
|
||||
#ifdef __linux__
|
||||
" -E, --transparent Transparent proxy mode\n"
|
||||
#endif
|
||||
" -c, --max-conn <count> Connection count limit, default 512\n"
|
||||
" -N, --no-domain Deny domain resolving\n"
|
||||
" -U, --no-udp Deny UDP association\n"
|
||||
|
@ -116,6 +119,9 @@ const struct option options[] = {
|
|||
{"version", 0, 0, 'v'},
|
||||
{"ip", 1, 0, 'i'},
|
||||
{"port", 1, 0, 'p'},
|
||||
#ifdef __linux__
|
||||
{"transparent", 0, 0, 'E'},
|
||||
#endif
|
||||
{"conn-ip", 1, 0, 'I'},
|
||||
{"buf-size", 1, 0, 'b'},
|
||||
{"max-conn", 1, 0, 'c'},
|
||||
|
@ -492,6 +498,11 @@ int main(int argc, char **argv)
|
|||
case 'U':
|
||||
params.udp = 0;
|
||||
break;
|
||||
#ifdef __linux__
|
||||
case 'E':
|
||||
params.transparent = 1;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'h':
|
||||
printf(help_text);
|
||||
|
@ -868,6 +879,7 @@ int main(int argc, char **argv)
|
|||
clear_params();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int status = run((struct sockaddr_ina *)¶ms.laddr);
|
||||
clear_params();
|
||||
return status;
|
||||
|
|
1
params.h
1
params.h
|
@ -105,6 +105,7 @@ struct params {
|
|||
size_t bfsize;
|
||||
struct sockaddr_in6 baddr;
|
||||
struct sockaddr_in6 laddr;
|
||||
char transparent;
|
||||
struct mphdr *mempool;
|
||||
|
||||
char *protect_path;
|
||||
|
|
58
proxy.c
58
proxy.c
|
@ -32,9 +32,13 @@
|
|||
#if defined(__linux__) && defined(__GLIBC__)
|
||||
extern int accept4(int, struct sockaddr *__restrict, socklen_t *__restrict, int);
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
/* For SO_ORIGINAL_DST only (which is 0x50) */
|
||||
#include "linux/netfilter_ipv4.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int NOT_EXIT = 1;
|
||||
|
||||
static void on_cancel(int sig) {
|
||||
|
@ -197,6 +201,17 @@ int resp_error(int fd, int e, int flag)
|
|||
}
|
||||
return resp_s5_error(fd, e);
|
||||
}
|
||||
#ifdef __linux__
|
||||
if (params.transparent &&
|
||||
(e == ECONNREFUSED || e == ETIMEDOUT)) {
|
||||
struct linger l = { .l_onoff = 1 };
|
||||
if (setsockopt(fd,
|
||||
SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {
|
||||
uniperror("setsockopt SO_LINGER");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -242,7 +257,7 @@ int s5_get_addr(char *buffer, size_t n,
|
|||
struct sockaddr_ina *addr, int type)
|
||||
{
|
||||
if (n < S_SIZE_MIN) {
|
||||
LOG(LOG_E, "ss: request to small\n");
|
||||
LOG(LOG_E, "ss: request too small\n");
|
||||
return -S_ER_GEN;
|
||||
}
|
||||
struct s5_req *r = (struct s5_req *)buffer;
|
||||
|
@ -519,6 +534,34 @@ int udp_associate(struct poolhd *pool,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static inline int transp_conn(struct poolhd *pool, struct eval *val)
|
||||
{
|
||||
struct sockaddr_ina remote, self;
|
||||
socklen_t rlen = sizeof(remote), slen = sizeof(self);
|
||||
if (getsockopt(val->fd,
|
||||
IPPROTO_IP, SO_ORIGINAL_DST, &remote, &rlen) != 0) {
|
||||
uniperror("getsockopt SO_ORIGINAL_DST");
|
||||
return -1;
|
||||
}
|
||||
if (getsockname(val->fd, &self.sa, &slen) < 0) {
|
||||
uniperror("getsockname");
|
||||
return -1;
|
||||
}
|
||||
if (self.sa.sa_family == remote.sa.sa_family &&
|
||||
self.in.sin_port == remote.in.sin_port &&
|
||||
addr_equ(&self, &remote)) {
|
||||
LOG(LOG_E, "connect to self, ignore\n");
|
||||
return -1;
|
||||
}
|
||||
int error = connect_hook(pool, val, &remote, EV_CONNECT);
|
||||
if (error) {
|
||||
uniperror("connect_hook");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int on_accept(struct poolhd *pool, struct eval *val)
|
||||
{
|
||||
|
@ -565,6 +608,12 @@ static inline int on_accept(struct poolhd *pool, struct eval *val)
|
|||
continue;
|
||||
}
|
||||
rval->in6 = client.in6;
|
||||
#ifdef __linux__
|
||||
if (params.transparent && transp_conn(pool, rval) < 0) {
|
||||
close(c);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -753,7 +802,7 @@ static inline int on_request(struct poolhd *pool, struct eval *val,
|
|||
return 0;
|
||||
}
|
||||
if (n < S_SIZE_MIN) {
|
||||
LOG(LOG_E, "ss: request to small (%zd)\n", n);
|
||||
LOG(LOG_E, "ss: request too small (%zd)\n", n);
|
||||
return -1;
|
||||
}
|
||||
struct s5_req *r = (struct s5_req *)buffer;
|
||||
|
@ -844,7 +893,7 @@ void close_conn(struct poolhd *pool, struct eval *val)
|
|||
}
|
||||
|
||||
|
||||
int event_loop(int srvfd)
|
||||
int event_loop(int srvfd)
|
||||
{
|
||||
size_t bfsize = params.bfsize;
|
||||
|
||||
|
@ -982,4 +1031,3 @@ int run(struct sockaddr_ina *srv)
|
|||
}
|
||||
return event_loop(fd);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue