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-iface4=<interface_name> ; bind to the first ipv4 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-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
@ -306,8 +310,12 @@ tpws can bind to multiple interfaces and IP addresses (up to 32).
Port number is always the same.
Parameters --bind-iface* и --bind-addr create new 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.
--bind-iface6 with --bind-linklocal=prefer first selects link local then a private address fd00::/8 then a global address.
Выбор режима использования link local ipv6 адресов (fe80:://8) :
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.
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

View File

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

View File

@ -6,13 +6,14 @@
#include "strpool.h"
enum splithttpreq { split_none = 0, split_method, split_host };
enum bindll { unwanted=0, no, prefer, force };
#define MAX_BINDS 32
struct bind_s
{
char bindaddr[64],bindiface[IF_NAMESIZE];
bool bind_if6;
bool bindll,bindll_force;
enum bindll bindll;
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-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-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-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"
" * 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"
@ -290,9 +291,15 @@ void parse_params(int argc, char *argv[])
case 5: /* bind-linklocal */
checkbind_clean();
params.binds[params.binds_last].bindll = true;
if (!strcmp(optarg, "force"))
params.binds[params.binds_last].bindll_force=true;
else if (strcmp(optarg, "prefer"))
if (!strcmp(optarg, "no"))
params.binds[params.binds_last].bindll=no;
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);
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;
bool found=false;
bool bindll_want = bindll==prefer || bindll==force;
if (getifaddrs(&addrs)<0)
return false;
@ -526,11 +534,13 @@ static bool find_listen_addr(struct sockaddr_storage *salisten, const char *bind
// ipv6 links locals are fe80::/10
else if (a->ifa_addr->sa_family==AF_INET6
&&
(!*bindiface && bindll ||
(!*bindiface && (bindll==prefer || bindll==force) ||
*bindiface && bind_if6 && !strcmp(a->ifa_name, bindiface))
&&
(bindll && 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==force && 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;
@ -640,6 +650,7 @@ struct salisten_s
int ipv6_only;
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 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++)
{
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,
params.binds[i].bindaddr,params.binds[i].bindiface,params.binds[i].bind_if6,params.binds[i].bindll,params.binds[i].bindll_force,
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,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);
if_index=0;
if (*params.binds[i].bindiface)
@ -716,27 +727,37 @@ int main(int argc, char *argv[])
if (*params.binds[i].bindiface || params.binds[i].bindll)
{
bool found;
enum bindll bindll_1;
int sec=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);
if (params.binds[i].bindll && !params.binds[i].bindll_force && params.binds[i].bind_wait_ip_ll>0)
printf("during the first %d second(s) accepting only link locals...\n", params.binds[i].bind_wait_ip_ll);
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);
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(;;)
{
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
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 :
params.binds[i].bindll;
if (sec && sec==params.binds[i].bind_wait_ip_ll)
{
if (params.binds[i].bindll==prefer)
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 (params.binds[i].bindll && !params.binds[i].bindll_force && sec>=params.binds[i].bind_wait_ip_ll)
if ((found = find_listen_addr(&list[i].salisten,params.binds[i].bindiface,params.binds[i].bind_if6,false,&if_index)))
{
printf("link local address wait timeout. using global address\n");
break;
}
if (sec>=params.binds[i].bind_wait_ip)
break;