tpws: more bind-linklocal modes

This commit is contained in:
bol-van 2021-03-08 22:33:21 +03:00
parent 4016534dfe
commit be0b76c02b
13 changed files with 69 additions and 31 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -260,7 +260,11 @@ tpws is transparent proxy.
--bind-addr=<v4_addr>|<v6_addr>; for v6 link locals append %interface_name : fe80::1%br-lan --bind-addr=<v4_addr>|<v6_addr>; for v6 link locals append %interface_name : fe80::1%br-lan
--bind-iface4=<interface_name> ; bind to the first ipv4 addr of interface --bind-iface4=<interface_name> ; bind to the first ipv4 addr of interface
--bind-iface6=<interface_name> ; bind to the first ipv6 addr of interface --bind-iface6=<interface_name> ; bind to the first ipv6 addr of interface
--bind-linklocal=prefer|force ; prefer or force ipv6 link local --bind-linklocal=no|unwanted|prefer|force
; no : bind only to global ipv6
; unwanted (default) : prefer global address, then LL
; prefer : prefer LL, then global
; force : LL only
--bind-wait-ifup=<sec> ; wait for interface to appear and up --bind-wait-ifup=<sec> ; wait for interface to appear and up
--bind-wait-ip=<sec> ; after ifup wait for ip address to appear up to N seconds --bind-wait-ip=<sec> ; after ifup wait for ip address to appear up to N seconds
--bind-wait-ip-linklocal=<sec> ; accept only link locals first N seconds then any --bind-wait-ip-linklocal=<sec> ; accept only link locals first N seconds then any
@ -306,8 +310,12 @@ tpws can bind to multiple interfaces and IP addresses (up to 32).
Port number is always the same. Port number is always the same.
Parameters --bind-iface* и --bind-addr create new bind. Parameters --bind-iface* и --bind-addr create new bind.
Other parameters --bind-* are related to the last bind. Other parameters --bind-* are related to the last bind.
--bind-iface6 without --bind-linklocal first selects a private address fd00::/8 then a global address, and last link local. Выбор режима использования link local ipv6 адресов (fe80:://8) :
--bind-iface6 with --bind-linklocal=prefer first selects link local then a private address fd00::/8 then a global address. ipv6 link local usage modes :
--bind-iface6 --bind-linklocal=no : first selects private address fd00::/8, then global address
--bind-iface6 --bind-linklocal=unwanted : first selects private address fd00::/8, then global address, then LL
--bind-iface6 --bind-linklocal=prefer : first selects LL, then private address fd00::/8, then global address
--bind-iface6 --bind-linklocal=force : select only LL
To bind to all ipv4 specify --bind-addr "0.0.0.0", all ipv6 - "::". --bind-addr="" - mean bind to all ipv4 and ipv6. To bind to all ipv4 specify --bind-addr "0.0.0.0", all ipv6 - "::". --bind-addr="" - mean bind to all ipv4 and ipv6.
If no binds are specified default bind to all ipv4 and ipv6 addresses is created. If no binds are specified default bind to all ipv4 and ipv6 addresses is created.
To bind to a specific link local address do : --bind-iface6=fe80::aaaa:bbbb:cccc:dddd%iface-name To bind to a specific link local address do : --bind-iface6=fe80::aaaa:bbbb:cccc:dddd%iface-name

View File

@ -313,13 +313,19 @@ tpws - это transparent proxy.
--uid=uid[:gid] ; менять uid процесса --uid=uid[:gid] ; менять uid процесса
--bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес --bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес
; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan ; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan
--bind-linklocal=prefer|force ; если prefer, то найти link local от iface6. если не найдено - использовать первый адрес любого типа. --bind-linklocal=no|unwanted|prefer|force
; если force и link local не найден - выход по ошибке. ; no : биндаться только на global ipv6
; unwanted (default) : предпочтительно global, если нет - LL
; prefer : предпочительно LL, если нет - global
; force : биндаться только на LL
--bind-iface4=<iface> ; слушать на первом ipv4 интерфейса iface --bind-iface4=<iface> ; слушать на первом ipv4 интерфейса iface
--bind-iface6=<iface> ; слушать на первом ipv6 интерфейса iface --bind-iface6=<iface> ; слушать на первом ipv6 интерфейса iface
--bind-wait-ifup=<sec> ; ждать до N секунд появления и поднятия интерфейса --bind-wait-ifup=<sec> ; ждать до N секунд появления и поднятия интерфейса
--bind-wait-ip=<sec> ; ждать до N секунд получения IP адреса (если задан --bind-wait-ifup - время идет после поднятия интерфейса) --bind-wait-ip=<sec> ; ждать до N секунд получения IP адреса (если задан --bind-wait-ifup - время идет после поднятия интерфейса)
--bind-wait-ip-linklocal=<sec> ; (только если заданы --bind-wait-ip и --bind-linklocal=prefer) согласиться на global address после N секунд --bind-wait-ip-linklocal=<sec>
; имеет смысл только при задании --bind-wait-ip
; --bind-linklocal=unwanted : согласиться на LL после N секунд
; --bind-linklocal=prefer : согласиться на global address после N секунд
--bind-wait-only ; подождать все бинды и выйти. результат 0 в случае успеха, иначе не 0. --bind-wait-only ; подождать все бинды и выйти. результат 0 в случае успеха, иначе не 0.
--socks ; вместо прозрачного прокси реализовать socks4/5 proxy --socks ; вместо прозрачного прокси реализовать socks4/5 proxy
--no-resolve ; запретить ресолвинг имен через socks5 --no-resolve ; запретить ресолвинг имен через socks5
@ -389,9 +395,11 @@ tpws может биндаться на множество интерфейсо
Параметры --bind-iface* и --bind-addr создают новый бинд. Параметры --bind-iface* и --bind-addr создают новый бинд.
Остальные параметры --bind-* относятся к последнему бинду. Остальные параметры --bind-* относятся к последнему бинду.
Для бинда на все ipv4 укажите --bind-addr "0.0.0.0", на все ipv6 - "::". --bind-addr="" - биндаемся на все ipv4 и ipv6. Для бинда на все ipv4 укажите --bind-addr "0.0.0.0", на все ipv6 - "::". --bind-addr="" - биндаемся на все ipv4 и ipv6.
--bind-iface6 без --bind-linklocal выбирает сначала приватный адрес fd00::/8, затем глобальный адрес, затем link local. Выбор режима использования link local ipv6 адресов (fe80:://8) :
--bind-iface6 с --bind-linklocal=prefer выбирает сначала link local, затем приватный адрес fd00::/8, затем глобальный адрес. --bind-iface6 --bind-linklocal=no : сначала приватный адрес fd00::/8, затем глобальный адрес
--bind-iface6 с --bind-linklocal=force выбирает только link local --bind-iface6 --bind-linklocal=unwanted : сначала приватный адрес fd00::/8, затем глобальный адрес, затем link local.
--bind-iface6 --bind-linklocal=prefer : сначала link local, затем приватный адрес fd00::/8, затем глобальный адрес.
--bind-iface6 --bind-linklocal=force : только link local
Если не указано ни одного бинда, то создается бинд по умолчанию на все адреса всех интерфейсов. Если не указано ни одного бинда, то создается бинд по умолчанию на все адреса всех интерфейсов.
Для бинда на конкретный link-local address делаем так : --bind-iface6=fe80::aaaa:bbbb:cccc:dddd%iface-name Для бинда на конкретный link-local address делаем так : --bind-iface6=fe80::aaaa:bbbb:cccc:dddd%iface-name
Параметры --bind-wait* могут помочь в ситуациях, когда нужно взять IP с интерфейса, но его еще нет, он не поднят Параметры --bind-wait* могут помочь в ситуациях, когда нужно взять IP с интерфейса, но его еще нет, он не поднят

View File

@ -6,13 +6,14 @@
#include "strpool.h" #include "strpool.h"
enum splithttpreq { split_none = 0, split_method, split_host }; enum splithttpreq { split_none = 0, split_method, split_host };
enum bindll { unwanted=0, no, prefer, force };
#define MAX_BINDS 32 #define MAX_BINDS 32
struct bind_s struct bind_s
{ {
char bindaddr[64],bindiface[IF_NAMESIZE]; char bindaddr[64],bindiface[IF_NAMESIZE];
bool bind_if6; bool bind_if6;
bool bindll,bindll_force; enum bindll bindll;
int bind_wait_ifup,bind_wait_ip,bind_wait_ip_ll; int bind_wait_ifup,bind_wait_ip,bind_wait_ip_ll;
}; };

View File

@ -113,10 +113,11 @@ static void exithelp()
" --bind-addr=<v4_addr>|<v6_addr>; for v6 link locals append %%interface_name\n" " --bind-addr=<v4_addr>|<v6_addr>; for v6 link locals append %%interface_name\n"
" --bind-iface4=<interface_name>\t; bind to the first ipv4 addr of interface\n" " --bind-iface4=<interface_name>\t; bind to the first ipv4 addr of interface\n"
" --bind-iface6=<interface_name>\t; bind to the first ipv6 addr of interface\n" " --bind-iface6=<interface_name>\t; bind to the first ipv6 addr of interface\n"
" --bind-linklocal=prefer|force\t; prefer or force ipv6 link local\n" " --bind-linklocal=no|unwanted|prefer|force\n"
"\t\t\t\t; prohibit, accept, prefer or force ipv6 link local bind\n"
" --bind-wait-ifup=<sec>\t\t; wait for interface to appear and up\n" " --bind-wait-ifup=<sec>\t\t; wait for interface to appear and up\n"
" --bind-wait-ip=<sec>\t\t; after ifup wait for ip address to appear up to N seconds\n" " --bind-wait-ip=<sec>\t\t; after ifup wait for ip address to appear up to N seconds\n"
" --bind-wait-ip-linklocal=<sec>\t; accept only link locals first N seconds then any\n" " --bind-wait-ip-linklocal=<sec>\t; (prefer) accept only LL first N seconds then any (unwanted) accept only globals first N seconds then LL\n"
" --bind-wait-only\t\t; wait for bind conditions satisfaction then exit. return code 0 if success.\n" " --bind-wait-only\t\t; wait for bind conditions satisfaction then exit. return code 0 if success.\n"
" * multiple binds are supported. each bind-addr, bind-iface* start new bind\n" " * multiple binds are supported. each bind-addr, bind-iface* start new bind\n"
" --port=<port>\t\t\t; only one port number for all binds is supported\n" " --port=<port>\t\t\t; only one port number for all binds is supported\n"
@ -290,9 +291,15 @@ void parse_params(int argc, char *argv[])
case 5: /* bind-linklocal */ case 5: /* bind-linklocal */
checkbind_clean(); checkbind_clean();
params.binds[params.binds_last].bindll = true; params.binds[params.binds_last].bindll = true;
if (!strcmp(optarg, "force")) if (!strcmp(optarg, "no"))
params.binds[params.binds_last].bindll_force=true; params.binds[params.binds_last].bindll=no;
else if (strcmp(optarg, "prefer")) else if (!strcmp(optarg, "prefer"))
params.binds[params.binds_last].bindll=prefer;
else if (!strcmp(optarg, "force"))
params.binds[params.binds_last].bindll=force;
else if (!strcmp(optarg, "unwanted"))
params.binds[params.binds_last].bindll=unwanted;
else
{ {
fprintf(stderr, "invalid parameter in bind-linklocal : %s\n",optarg); fprintf(stderr, "invalid parameter in bind-linklocal : %s\n",optarg);
exit_clean(1); exit_clean(1);
@ -497,10 +504,11 @@ void parse_params(int argc, char *argv[])
} }
static bool find_listen_addr(struct sockaddr_storage *salisten, const char *bindiface, bool bind_if6, bool bindll, int *if_index) static bool find_listen_addr(struct sockaddr_storage *salisten, const char *bindiface, bool bind_if6, enum bindll bindll, int *if_index)
{ {
struct ifaddrs *addrs,*a; struct ifaddrs *addrs,*a;
bool found=false; bool found=false;
bool bindll_want = bindll==prefer || bindll==force;
if (getifaddrs(&addrs)<0) if (getifaddrs(&addrs)<0)
return false; return false;
@ -526,11 +534,13 @@ static bool find_listen_addr(struct sockaddr_storage *salisten, const char *bind
// ipv6 links locals are fe80::/10 // ipv6 links locals are fe80::/10
else if (a->ifa_addr->sa_family==AF_INET6 else if (a->ifa_addr->sa_family==AF_INET6
&& &&
(!*bindiface && bindll || (!*bindiface && (bindll==prefer || bindll==force) ||
*bindiface && bind_if6 && !strcmp(a->ifa_name, bindiface)) *bindiface && bind_if6 && !strcmp(a->ifa_name, bindiface))
&& &&
(bindll && is_linklocal((struct sockaddr_in6*)a->ifa_addr) || (bindll==force && is_linklocal((struct sockaddr_in6*)a->ifa_addr) ||
!bindll && (pass==2 || pass==0 && is_private6((struct sockaddr_in6*)a->ifa_addr) || pass==1 && !is_linklocal((struct sockaddr_in6*)a->ifa_addr))) bindll==prefer && (pass==0 && is_linklocal((struct sockaddr_in6*)a->ifa_addr) || pass==1 && is_private6((struct sockaddr_in6*)a->ifa_addr) || pass==2) ||
bindll==no && (pass==0 && is_private6((struct sockaddr_in6*)a->ifa_addr) || pass==1 && !is_linklocal((struct sockaddr_in6*)a->ifa_addr)) ||
bindll==unwanted && (pass==0 && is_private6((struct sockaddr_in6*)a->ifa_addr) || pass==1 && !is_linklocal((struct sockaddr_in6*)a->ifa_addr) || pass==2))
) )
{ {
salisten->ss_family = AF_INET6; salisten->ss_family = AF_INET6;
@ -640,6 +650,7 @@ struct salisten_s
int ipv6_only; int ipv6_only;
int bind_wait_ip_left; // how much seconds left from bind_wait_ip int bind_wait_ip_left; // how much seconds left from bind_wait_ip
}; };
static const char *bindll_s[] = { "unwanted","no","prefer","force" };
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int i, listen_fd[MAX_BINDS], yes = 1, retval = 0, if_index, exit_v=EXIT_FAILURE; int i, listen_fd[MAX_BINDS], yes = 1, retval = 0, if_index, exit_v=EXIT_FAILURE;
@ -662,8 +673,8 @@ int main(int argc, char *argv[])
for(i=0;i<=params.binds_last;i++) for(i=0;i<=params.binds_last;i++)
{ {
VPRINT("Prepare bind %d : addr=%s iface=%s v6=%u link_local=%u link_local_force=%u wait_ifup=%d wait_ip=%d wait_ip_ll=%d",i, VPRINT("Prepare bind %d : addr=%s iface=%s v6=%u link_local=%s wait_ifup=%d wait_ip=%d wait_ip_ll=%d",i,
params.binds[i].bindaddr,params.binds[i].bindiface,params.binds[i].bind_if6,params.binds[i].bindll,params.binds[i].bindll_force, params.binds[i].bindaddr,params.binds[i].bindiface,params.binds[i].bind_if6,bindll_s[params.binds[i].bindll],
params.binds[i].bind_wait_ifup,params.binds[i].bind_wait_ip,params.binds[i].bind_wait_ip_ll); params.binds[i].bind_wait_ifup,params.binds[i].bind_wait_ip,params.binds[i].bind_wait_ip_ll);
if_index=0; if_index=0;
if (*params.binds[i].bindiface) if (*params.binds[i].bindiface)
@ -716,26 +727,36 @@ int main(int argc, char *argv[])
if (*params.binds[i].bindiface || params.binds[i].bindll) if (*params.binds[i].bindiface || params.binds[i].bindll)
{ {
bool found; bool found;
enum bindll bindll_1;
int sec=0; int sec=0;
if (params.binds[i].bind_wait_ip > 0) if (params.binds[i].bind_wait_ip > 0)
{ {
printf("waiting for ip on %s for up to %d second(s)...\n", *params.binds[i].bindiface ? params.binds[i].bindiface : "<any>", params.binds[i].bind_wait_ip); printf("waiting for ip on %s for up to %d second(s)...\n", *params.binds[i].bindiface ? params.binds[i].bindiface : "<any>", params.binds[i].bind_wait_ip);
if (params.binds[i].bindll && !params.binds[i].bindll_force && params.binds[i].bind_wait_ip_ll>0) if (params.binds[i].bind_wait_ip_ll>0)
{
if (params.binds[i].bindll==prefer)
printf("during the first %d second(s) accepting only link locals...\n", params.binds[i].bind_wait_ip_ll); printf("during the first %d second(s) accepting only link locals...\n", params.binds[i].bind_wait_ip_ll);
else if (params.binds[i].bindll==unwanted)
printf("during the first %d second(s) accepting only ipv6 globals...\n", params.binds[i].bind_wait_ip_ll);
}
} }
for(;;) for(;;)
{ {
found = find_listen_addr(&list[i].salisten,params.binds[i].bindiface,params.binds[i].bind_if6,params.binds[i].bindll,&if_index); // allow, no, prefer, force
if (found) break; bindll_1 = (params.binds[i].bindll==prefer && sec<params.binds[i].bind_wait_ip_ll) ? force :
(params.binds[i].bindll==unwanted && sec<params.binds[i].bind_wait_ip_ll) ? no :
if (params.binds[i].bindll && !params.binds[i].bindll_force && sec>=params.binds[i].bind_wait_ip_ll) params.binds[i].bindll;
if ((found = find_listen_addr(&list[i].salisten,params.binds[i].bindiface,params.binds[i].bind_if6,false,&if_index))) if (sec && sec==params.binds[i].bind_wait_ip_ll)
{ {
printf("link local address wait timeout. using global address\n"); if (params.binds[i].bindll==prefer)
break; printf("link local address wait timeout. now accepting globals\n");
else if (params.binds[i].bindll==unwanted)
printf("global ipv6 address wait timeout. now accepting link locals\n");
} }
found = find_listen_addr(&list[i].salisten,params.binds[i].bindiface,params.binds[i].bind_if6,bindll_1,&if_index);
if (found) break;
if (sec>=params.binds[i].bind_wait_ip) if (sec>=params.binds[i].bind_wait_ip)
break; break;