1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-11-25 19:09:52 +03:00

Merge pull request #1867 from hiura2023/master

Bind outgoing connection to a specific IP address
This commit is contained in:
Ilya Shipitsin 2023-09-10 17:18:31 +02:00 committed by GitHub
commit 205a94cda2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 575 additions and 32 deletions

View File

@ -6150,6 +6150,8 @@ void CmImportAccountMainEx(HWND hWnd, wchar_t *filename, bool overwrite)
t->ClientOption->RequireMonitorMode = old_option->RequireMonitorMode; t->ClientOption->RequireMonitorMode = old_option->RequireMonitorMode;
t->ClientOption->RequireBridgeRoutingMode = old_option->RequireBridgeRoutingMode; t->ClientOption->RequireBridgeRoutingMode = old_option->RequireBridgeRoutingMode;
t->ClientOption->DisableQoS = old_option->DisableQoS; t->ClientOption->DisableQoS = old_option->DisableQoS;
t->ClientOption->BindLocalIP = old_option->BindLocalIP;// Source IP address for outgoing connection
t->ClientOption->BindLocalPort = old_option->BindLocalPort;// Source port number for outgoing connection
// Inherit the authentication data // Inherit the authentication data
CiFreeClientAuth(t->ClientAuth); CiFreeClientAuth(t->ClientAuth);
@ -6456,9 +6458,55 @@ void CmDetailDlgUpdate(HWND hWnd, CM_ACCOUNT *a)
Disable(hWnd, R_BRIDGE); Disable(hWnd, R_BRIDGE);
Disable(hWnd, R_MONITOR); Disable(hWnd, R_MONITOR);
Disable(hWnd, R_NO_ROUTING); Disable(hWnd, R_NO_ROUTING);
#if TYPE_BINDLOCALIP
Disable(hWnd, E_BIND_LOCALIP);// Source IP address for outgoing connection
Disable(hWnd, E_BIND_LOCALPORT);// Source port number for outgoing connection
#endif
} }
} }
#if TYPE_BINDLOCALIP
// Set the value of the IP type
void SetIp(HWND hWnd, UINT id, IP* ip)
{
char tmp[MAX_SIZE];
// Validate arguments
if (hWnd == NULL || ip == NULL)
{
return;
}
IPToStr(tmp, sizeof(tmp), ip);
SetTextA(hWnd, id, tmp);
}
// Get an IP address
bool GetIp(HWND hWnd, UINT id, IP* ip)
{
char tmp[MAX_SIZE];
// Validate arguments
if (hWnd == NULL || ip == NULL)
{
return false;
}
Zero(ip, sizeof(IP));
if (GetTxtA(hWnd, id, tmp, sizeof(tmp)) == false)
{
return false;
}
if (StrToIP(ip, tmp) == false)
{
return false;
}
return true;
}
#endif
// Advanced Settings dialog procedure // Advanced Settings dialog procedure
UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param) UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)
{ {
@ -6495,6 +6543,11 @@ UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *pa
Check(hWnd, R_NO_ROUTING, a->ClientOption->NoRoutingTracking); Check(hWnd, R_NO_ROUTING, a->ClientOption->NoRoutingTracking);
Check(hWnd, R_DISABLE_QOS, a->ClientOption->DisableQoS); Check(hWnd, R_DISABLE_QOS, a->ClientOption->DisableQoS);
Check(hWnd, R_DISABLE_UDP, a->ClientOption->NoUdpAcceleration); Check(hWnd, R_DISABLE_UDP, a->ClientOption->NoUdpAcceleration);
#if TYPE_BINDLOCALIP
SetIp(hWnd, E_BIND_LOCALIP, &a->ClientOption->BindLocalIP);// Source IP address for outgoing connection
SetIntEx(hWnd, E_BIND_LOCALPORT, a->ClientOption->BindLocalPort);// Source port number for outgoing connection
//Disable(hWnd, E_BIND_LOCALPORT); // You can not edit
#endif
// Select the Connection Mode // Select the Connection Mode
if (a->LinkMode == false) if (a->LinkMode == false)
@ -6542,6 +6595,20 @@ UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *pa
Focus(hWnd, E_INTERVAL); Focus(hWnd, E_INTERVAL);
break; break;
} }
#if TYPE_BINDLOCALIP
// Source IP address for outgoing connection
IP tmpIP;
if (GetIp(hWnd, E_BIND_LOCALIP, &tmpIP) == false)
{
FocusEx(hWnd, E_BIND_LOCALIP);
break;
}
// Source port number for outgoing connection
if ((GetInt(hWnd, E_BIND_LOCALPORT) < 0) || (GetInt(hWnd, E_BIND_LOCALPORT) > 65535)){
FocusEx(hWnd, E_BIND_LOCALPORT);
break;
}
#endif
a->ClientOption->MaxConnection = num; a->ClientOption->MaxConnection = num;
a->ClientOption->AdditionalConnectionInterval = GetInt(hWnd, E_INTERVAL); a->ClientOption->AdditionalConnectionInterval = GetInt(hWnd, E_INTERVAL);
@ -6559,6 +6626,10 @@ UINT CmDetailDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *pa
a->ClientOption->NoRoutingTracking = IsChecked(hWnd, R_NO_ROUTING); a->ClientOption->NoRoutingTracking = IsChecked(hWnd, R_NO_ROUTING);
a->ClientOption->DisableQoS = IsChecked(hWnd, R_DISABLE_QOS); a->ClientOption->DisableQoS = IsChecked(hWnd, R_DISABLE_QOS);
a->ClientOption->NoUdpAcceleration = IsChecked(hWnd, R_DISABLE_UDP); a->ClientOption->NoUdpAcceleration = IsChecked(hWnd, R_DISABLE_UDP);
#if TYPE_BINDLOCALIP
a->ClientOption->BindLocalIP = tmpIP;// Source IP address for outgoing connection
a->ClientOption->BindLocalPort = GetInt(hWnd, E_BIND_LOCALPORT);// Source port number for outgoing connection
#endif
if (a->LinkMode) if (a->LinkMode)
{ {

View File

@ -4345,6 +4345,9 @@ void InRpcClientOption(CLIENT_OPTION *c, PACK *p)
PackGetStr(p, "CustomHttpHeader", c->CustomHttpHeader, sizeof(c->CustomHttpHeader)); PackGetStr(p, "CustomHttpHeader", c->CustomHttpHeader, sizeof(c->CustomHttpHeader));
PackGetStr(p, "HubName", c->HubName, sizeof(c->HubName)); PackGetStr(p, "HubName", c->HubName, sizeof(c->HubName));
PackGetStr(p, "DeviceName", c->DeviceName, sizeof(c->DeviceName)); PackGetStr(p, "DeviceName", c->DeviceName, sizeof(c->DeviceName));
PackGetIp(p, "BindLocalIP", &c->BindLocalIP);// Source IP address for outgoing connection
c->BindLocalPort = PackGetInt(p, "BindLocalPort");// Source port nubmer for outgoing connection
c->UseEncrypt = PackGetInt(p, "UseEncrypt") ? true : false; c->UseEncrypt = PackGetInt(p, "UseEncrypt") ? true : false;
c->UseCompress = PackGetInt(p, "UseCompress") ? true : false; c->UseCompress = PackGetInt(p, "UseCompress") ? true : false;
c->HalfConnection = PackGetInt(p, "HalfConnection") ? true : false; c->HalfConnection = PackGetInt(p, "HalfConnection") ? true : false;
@ -4405,6 +4408,8 @@ void OutRpcClientOption(PACK *p, CLIENT_OPTION *c)
PackAddBool(p, "FromAdminPack", c->FromAdminPack); PackAddBool(p, "FromAdminPack", c->FromAdminPack);
PackAddBool(p, "NoUdpAcceleration", c->NoUdpAcceleration); PackAddBool(p, "NoUdpAcceleration", c->NoUdpAcceleration);
PackAddData(p, "HostUniqueKey", c->HostUniqueKey, SHA1_SIZE); PackAddData(p, "HostUniqueKey", c->HostUniqueKey, SHA1_SIZE);
PackAddIp(p, "BindLocalIP", &c->BindLocalIP);// Source IP address for outgoing connection
PackAddInt(p, "BindLocalPort", c->BindLocalPort);// Source port number for outgoing connection
} }
// CLIENT_AUTH // CLIENT_AUTH
@ -9299,6 +9304,8 @@ CLIENT_OPTION *CiLoadClientOption(FOLDER *f)
o->DisableQoS = CfgGetBool(f, "DisableQoS"); o->DisableQoS = CfgGetBool(f, "DisableQoS");
o->FromAdminPack = CfgGetBool(f, "FromAdminPack"); o->FromAdminPack = CfgGetBool(f, "FromAdminPack");
o->NoUdpAcceleration = CfgGetBool(f, "NoUdpAcceleration"); o->NoUdpAcceleration = CfgGetBool(f, "NoUdpAcceleration");
CfgGetIp(f, "BindLocalIP", &o->BindLocalIP);// Source IP address for outgoing connection
o->BindLocalPort = CfgGetInt(f, "BindLocalPort");// Source port number for outgoing connection
b = CfgGetBuf(f, "HostUniqueKey"); b = CfgGetBuf(f, "HostUniqueKey");
if (b != NULL) if (b != NULL)
@ -9853,6 +9860,8 @@ void CiWriteClientOption(FOLDER *f, CLIENT_OPTION *o)
CfgAddBool(f, "RequireBridgeRoutingMode", o->RequireBridgeRoutingMode); CfgAddBool(f, "RequireBridgeRoutingMode", o->RequireBridgeRoutingMode);
CfgAddBool(f, "DisableQoS", o->DisableQoS); CfgAddBool(f, "DisableQoS", o->DisableQoS);
CfgAddBool(f, "NoUdpAcceleration", o->NoUdpAcceleration); CfgAddBool(f, "NoUdpAcceleration", o->NoUdpAcceleration);
CfgAddIp(f, "BindLocalIP", &o->BindLocalIP);// Source IP address for outgoing connection
CfgAddInt(f, "BindLocalPort", o->BindLocalPort);// Source port number for outgoing connection
if (o->FromAdminPack) if (o->FromAdminPack)
{ {

View File

@ -58,6 +58,7 @@ struct RC4_KEY_PAIR
UCHAR ServerToClientKey[16]; UCHAR ServerToClientKey[16];
UCHAR ClientToServerKey[16]; UCHAR ClientToServerKey[16];
}; };
#define TYPE_BINDLOCALIP 1 // Enable HMI user to edit Source IP address & Source port number for outgoing connection
// Client Options // Client Options
// Do not change item size or order and only add new items at the end! // Do not change item size or order and only add new items at the end!
@ -106,6 +107,8 @@ struct CLIENT_OPTION
UCHAR HostUniqueKey[SHA1_SIZE]; // Host unique key UCHAR HostUniqueKey[SHA1_SIZE]; // Host unique key
char CustomHttpHeader[HTTP_CUSTOM_HEADER_MAX_SIZE]; // Custom HTTP proxy header char CustomHttpHeader[HTTP_CUSTOM_HEADER_MAX_SIZE]; // Custom HTTP proxy header
char HintStr[MAX_HOST_NAME_LEN + 1]; // Hint string for NAT-T char HintStr[MAX_HOST_NAME_LEN + 1]; // Hint string for NAT-T
IP BindLocalIP; // Source IP address for outgoing connection
UINT BindLocalPort; // Source port number for outgoing connection
}; };
// Client authentication data // Client authentication data

View File

@ -6196,6 +6196,8 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect)
{ {
volatile bool *cancel_flag = NULL; volatile bool *cancel_flag = NULL;
char hostname[MAX_HOST_NAME_LEN]; char hostname[MAX_HOST_NAME_LEN];
char localaddr[MAX_HOST_NAME_LEN];
bool save_resolved_ip = false; bool save_resolved_ip = false;
CLIENT_OPTION *o; CLIENT_OPTION *o;
SESSION *sess; SESSION *sess;
@ -6255,10 +6257,48 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect)
if (o->PortUDP == 0) if (o->PortUDP == 0)
{ {
IP *localIP;
UINT localport;
// Top of Bind outgoing connection
// Decide the binding operation which is explicitly executed on the client-side
// In the case of first TCP/IP connection
if (additional_connect == false) {
if (sess->ClientOption->NoRoutingTracking == false) {
localIP = BIND_LOCALIP_NULL; // Specify not to bind
}
else {
Debug("ClientConnectGetSocket(): Using client option %r and %d for binding\n"
, sess->ClientOption->BindLocalIP, sess->ClientOption->BindLocalPort);
// Nonzero address is for source IP address to bind. Zero address is for dummy not to bind.
if (IsZeroIP(&sess->ClientOption->BindLocalIP) == true) {
localIP = BIND_LOCALIP_NULL;
}
else {
localIP = &sess->ClientOption->BindLocalIP;
}
}
}
// In the case of second and subsequent TCP/IP connections
else {
// Bind the socket to the actual local IP address of first TCP / IP connection
localIP = &sess->LocalIP_CacheForNextConnect;
//localIP = BIND_LOCALIP_NULL; // Specify not to bind for test
}
if (sess->ClientOption->BindLocalPort == 0) {
localport = BIND_LOCALPORT_NULL;
}
else {
localport = sess->ClientOption->BindLocalPort + Count(sess->Connection->CurrentNumConnection) - 1;
Debug("ClientConnectGetSocket(): Additional port number %u\n", localport);
}
// Bottom of Bind outgoing connection
// If additional_connect == false, enable trying to NAT-T connection // If additional_connect == false, enable trying to NAT-T connection
// If additional_connect == true, follow the IsRUDPSession setting in this session // If additional_connect == true, follow the IsRUDPSession setting in this session
// In additional connect or redirect we do not need ssl verification as the certificate is always compared with a saved one // In additional connect or redirect we do not need ssl verification as the certificate is always compared with a saved one
sock = TcpIpConnectEx2(hostname, c->ServerPort, sock = BindTcpIpConnectEx2(localIP, localport, hostname, c->ServerPort,
(bool *)cancel_flag, c->hWndForUI, &nat_t_err, (additional_connect ? (!sess->IsRUDPSession) : false), (bool *)cancel_flag, c->hWndForUI, &nat_t_err, (additional_connect ? (!sess->IsRUDPSession) : false),
true, ((additional_connect || c->UseTicket) ? NULL : sess->SslOption), &ssl_err, o->HintStr, &resolved_ip); true, ((additional_connect || c->UseTicket) ? NULL : sess->SslOption), &ssl_err, o->HintStr, &resolved_ip);
} }
@ -6328,6 +6368,33 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect)
StrCpy(in.HttpCustomHeader, sizeof(in.HttpCustomHeader), o->CustomHttpHeader); StrCpy(in.HttpCustomHeader, sizeof(in.HttpCustomHeader), o->CustomHttpHeader);
StrCpy(in.HttpUserAgent, sizeof(in.HttpUserAgent), c->Cedar->HttpUserAgent); StrCpy(in.HttpUserAgent, sizeof(in.HttpUserAgent), c->Cedar->HttpUserAgent);
// Top of Bind outgoing connection
// In the case of first TCP/IP connection
if (additional_connect == false) {
if (sess->ClientOption->NoRoutingTracking == false) {
in.BindLocalIP = BIND_LOCALIP_NULL; // Specify not to bind
}
else {
if (IsZeroIP(&sess->ClientOption->BindLocalIP) == true) {
in.BindLocalIP = BIND_LOCALIP_NULL;
}
else {
in.BindLocalIP = &sess->ClientOption->BindLocalIP;
}
}
}
// In the case of second and subsequent TCP/IP connections
else {
in.BindLocalIP = &sess->LocalIP_CacheForNextConnect;
}
if (sess->ClientOption->BindLocalPort == 0) {
in.BindLocalPort = BIND_LOCALPORT_NULL;
}
else {
in.BindLocalPort = sess->ClientOption->BindLocalPort + Count(sess->Connection->CurrentNumConnection) - 1;
}
// Bottom of Bind outgoing connection
#ifdef OS_WIN32 #ifdef OS_WIN32
in.Hwnd = c->hWndForUI; in.Hwnd = c->hWndForUI;
#endif #endif
@ -6338,13 +6405,16 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect)
switch (o->ProxyType) switch (o->ProxyType)
{ {
case PROXY_HTTP: case PROXY_HTTP:
ret = ProxyHttpConnect(&out, &in, cancel_flag); // ret = ProxyHttpConnect(&out, &in, cancel_flag);
ret = BindProxyHttpConnect(&out, &in, cancel_flag); // Bind outgoing connection
break; break;
case PROXY_SOCKS: case PROXY_SOCKS:
ret = ProxySocks4Connect(&out, &in, cancel_flag); // ret = ProxySocks4Connect(&out, &in, cancel_flag);
ret = BindProxySocks4Connect(&out, &in, cancel_flag); // Bind outgoing connection
break; break;
case PROXY_SOCKS5: case PROXY_SOCKS5:
ret = ProxySocks5Connect(&out, &in, cancel_flag); // ret = ProxySocks5Connect(&out, &in, cancel_flag);
ret = BindProxySocks5Connect(&out, &in, cancel_flag); // Bind outgoing connection
break; break;
default: default:
c->Err = ERR_INTERNAL_ERROR; c->Err = ERR_INTERNAL_ERROR;
@ -6379,6 +6449,25 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect)
Debug("ClientConnectGetSocket(): Saved %s IP address %r for future connections.\n", hostname, &resolved_ip); Debug("ClientConnectGetSocket(): Saved %s IP address %r for future connections.\n", hostname, &resolved_ip);
} }
// Top of Bind outgoing connection
IPToStr(localaddr, sizeof(localaddr), &sock->LocalIP);
// In the case of first TCP/IP connection, save the local IP address
if (additional_connect == false) {
c->Session->LocalIP_CacheForNextConnect = sock->LocalIP;
Debug("ClientConnectGetSocket(): Saved local IP address %r for future connections.\n", &sock->LocalIP);
}
// In the case of second and subsequent TCP/IP connections, check to see whether or not the local IP address is same as the first one
else {
if (memcmp(sock->LocalIP.address, c->Session->LocalIP_CacheForNextConnect.address, sizeof(sock->LocalIP.address)) == 0) {
Debug("ClientConnectGetSocket(): Binded local IP address %s OK\n", localaddr);
}
else {
Debug("ClientConnectGetSocket(): Binded local IP address %s NG\n", localaddr);
}
}
// Bottom of Bind outgoing connection
return sock; return sock;
} }
@ -6409,15 +6498,41 @@ UINT ProxyCodeToCedar(UINT code)
// TCP connection function // TCP connection function
SOCK *TcpConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, IP *ret_ip) SOCK *TcpConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, IP *ret_ip)
{ {
return TcpConnectEx4(hostname, port, timeout, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, NULL, NULL, NULL, ret_ip); return BindTcpConnectEx3(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, hostname, port, timeout, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, ret_ip);
} }
SOCK *TcpConnectEx4(char * hostname, UINT port, UINT timeout, bool * cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) SOCK *TcpConnectEx4(char * hostname, UINT port, UINT timeout, bool * cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip)
{
return BindTcpConnectEx4(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, hostname, port, timeout, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, ssl_option, ssl_err, hint_str, ret_ip);
}
// Connect with TCP/IP
SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip)
{
return BindTcpIpConnectEx(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, hostname, port, cancel_flag, hWnd, nat_t_error_code, no_nat_t, try_start_ssl, ret_ip);
}
SOCK *TcpIpConnectEx2(char * hostname, UINT port, bool * cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip)
{
return BindTcpIpConnectEx2(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, hostname, port, cancel_flag, hWnd, nat_t_error_code, no_nat_t, try_start_ssl, ssl_option, ssl_err, hint_str, ret_ip);
}
// TCP connection function
//SOCK* TcpConnectEx3(char* hostname, UINT port, UINT timeout, bool* cancel_flag, void* hWnd, bool no_nat_t, UINT* nat_t_error_code, bool try_start_ssl, IP* ret_ip)
SOCK *BindTcpConnectEx3(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, IP *ret_ip)
{
// return TcpConnectEx4(hostname, port, timeout, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, NULL, NULL, NULL, ret_ip);
return BindTcpConnectEx4(localIP, localport, hostname, port, timeout, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, NULL, NULL, NULL, ret_ip);
}
//SOCK *TcpConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip)
SOCK *BindTcpConnectEx4(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip)
{ {
#ifdef OS_WIN32 #ifdef OS_WIN32
if (hWnd == NULL) if (hWnd == NULL)
{ {
#endif // OS_WIN32 #endif // OS_WIN32
return ConnectEx5(hostname, port, timeout, cancel_flag, (no_nat_t ? NULL : VPN_RUDP_SVC_NAME), nat_t_error_code, try_start_ssl, true, ssl_option, ssl_err, hint_str, ret_ip); // return ConnectEx5(hostname, port, timeout, cancel_flag, (no_nat_t ? NULL : VPN_RUDP_SVC_NAME), nat_t_error_code, try_start_ssl, true, ssl_option, ssl_err, hint_str, ret_ip);
return BindConnectEx5(localIP, localport, hostname, port, timeout, cancel_flag, (no_nat_t ? NULL : VPN_RUDP_SVC_NAME), nat_t_error_code, try_start_ssl, true, ssl_option, ssl_err, hint_str, ret_ip);
#ifdef OS_WIN32 #ifdef OS_WIN32
} }
else else
@ -6428,11 +6543,14 @@ SOCK *TcpConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag,
} }
// Connect with TCP/IP // Connect with TCP/IP
SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip) //SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip)
SOCK *BindTcpIpConnectEx(IP *localIP, UINT localport, char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip)
{ {
return TcpIpConnectEx2(hostname, port, cancel_flag, hWnd, nat_t_error_code, no_nat_t, try_start_ssl, NULL, NULL, NULL, ret_ip); // return TcpIpConnectEx2(hostname, port, cancel_flag, hWnd, nat_t_error_code, no_nat_t, try_start_ssl, NULL, NULL, NULL, ret_ip);
return BindTcpIpConnectEx2(localIP, localport, hostname, port, cancel_flag, hWnd, nat_t_error_code, no_nat_t, try_start_ssl, NULL, NULL, NULL, ret_ip);
} }
SOCK *TcpIpConnectEx2(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) //SOCK *TcpIpConnectEx2(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip)
SOCK *BindTcpIpConnectEx2(IP *localIP, UINT localport, char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip)
{ {
SOCK *s = NULL; SOCK *s = NULL;
UINT dummy_int = 0; UINT dummy_int = 0;
@ -6447,7 +6565,8 @@ SOCK *TcpIpConnectEx2(char *hostname, UINT port, bool *cancel_flag, void *hWnd,
return NULL; return NULL;
} }
s = TcpConnectEx4(hostname, port, 0, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, ssl_option, ssl_err, hint_str, ret_ip); // s = TcpConnectEx4(hostname, port, 0, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, ssl_option, ssl_err, hint_str, ret_ip);
s = BindTcpConnectEx4(localIP, localport, hostname, port, 0, cancel_flag, hWnd, no_nat_t, nat_t_error_code, try_start_ssl, ssl_option, ssl_err, hint_str, ret_ip);
if (s == NULL) if (s == NULL)
{ {
return NULL; return NULL;

View File

@ -115,6 +115,11 @@ bool ClientConnect(CONNECTION *c);
SOCK *ClientConnectToServer(CONNECTION *c); SOCK *ClientConnectToServer(CONNECTION *c);
SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip); SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip);
SOCK *TcpIpConnectEx2(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip); SOCK *TcpIpConnectEx2(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip);
// New function named with prefix "Bind" binds outgoing connection to a specific address. New one is wrapped in original one.
SOCK* BindTcpIpConnectEx(IP *localIP, UINT localport, char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, IP *ret_ip);
SOCK* BindTcpIpConnectEx2(IP *localIP, UINT localport, char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip);
bool ClientUploadSignature(SOCK *s); bool ClientUploadSignature(SOCK *s);
bool ClientDownloadHello(CONNECTION *c, SOCK *s); bool ClientDownloadHello(CONNECTION *c, SOCK *s);
bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str); bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str);
@ -124,6 +129,10 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect);
SOCK *TcpConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, IP *ret_ip); SOCK *TcpConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, IP *ret_ip);
SOCK *TcpConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip); SOCK *TcpConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip);
// New function named with prefix "Bind" binds outgoing connection to a specific address. New one is wrapped in original one.
SOCK* BindTcpConnectEx3(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, IP *ret_ip);
SOCK* BindTcpConnectEx4(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip);
UINT ProxyCodeToCedar(UINT code); UINT ProxyCodeToCedar(UINT code);
void InitProtocol(); void InitProtocol();

View File

@ -41,7 +41,10 @@ typedef struct SETTING
char HubName[MAX_HUBNAME_LEN + 1]; // HUB name char HubName[MAX_HUBNAME_LEN + 1]; // HUB name
UCHAR HashedPassword[SHA1_SIZE]; // Password UCHAR HashedPassword[SHA1_SIZE]; // Password
CLIENT_OPTION ClientOption; // Client Option CLIENT_OPTION ClientOption; // Client Option
UCHAR Reserved[10240 - sizeof(UINT) * 8 - SHA1_SIZE - HTTP_CUSTOM_HEADER_MAX_SIZE - MAX_HOST_NAME_LEN - 1]; // Reserved area
#define SRC_SIZE (sizeof(IP) + sizeof(UINT)) // Source IP address & port number for outgoing connection
// UCHAR Reserved[10240 - sizeof(UINT) * 8 - SHA1_SIZE - HTTP_CUSTOM_HEADER_MAX_SIZE - MAX_HOST_NAME_LEN - 1]; // Reserved area
UCHAR Reserved[10240 - sizeof(UINT) * 8 - SHA1_SIZE - HTTP_CUSTOM_HEADER_MAX_SIZE - MAX_HOST_NAME_LEN - 1 - SRC_SIZE]; // Reserved area
} SETTING; } SETTING;
// Structure declaration // Structure declaration

View File

@ -609,6 +609,24 @@ void SessionMain(SESSION *s)
WHERE; WHERE;
} }
} }
// If all the specified number of tcp connections are not alive continuously, then terminate the session.
UINT num_tcp_conn = LIST_NUM(s->Connection->Tcp->TcpSockList);
UINT max_conn = s->ClientOption->MaxConnection;
if ((s->CurrentConnectionEstablishTime +
(UINT64)(s->ClientOption->AdditionalConnectionInterval * 1000 * 2 + CONNECTING_TIMEOUT * 2))
<= Tick64())
{
if (s->ClientOption->BindLocalPort != 0 || num_tcp_conn == 0)
{
timeouted = true;
WHERE;
}
}
//Debug("SessionMain(): The number of TCP connections short... Num_Tcp_Conn=%d Max_Conn=%d Curr_Conn_Time=%llu Tick64=%llu\n"
// , num_tcp_conn, max_conn, s->CurrentConnectionEstablishTime, Tick64());
} }
} }
@ -1430,6 +1448,7 @@ void ClientThread(THREAD *t, void *param)
while (true) while (true)
{ {
Zero(&s->ServerIP_CacheForNextConnect, sizeof(IP)); Zero(&s->ServerIP_CacheForNextConnect, sizeof(IP));
Zero(&s->LocalIP_CacheForNextConnect, sizeof(IP)); // Assigned by first outgoing connection
Zero(s->UnderlayProtocol, sizeof(s->UnderlayProtocol)); Zero(s->UnderlayProtocol, sizeof(s->UnderlayProtocol));
Zero(s->ProtocolDetails, sizeof(s->ProtocolDetails)); Zero(s->ProtocolDetails, sizeof(s->ProtocolDetails));

View File

@ -130,6 +130,7 @@ struct SESSION
UCHAR Padding[2]; UCHAR Padding[2];
IP ServerIP_CacheForNextConnect; // Server IP, cached for next connect IP ServerIP_CacheForNextConnect; // Server IP, cached for next connect
IP LocalIP_CacheForNextConnect; // Local IP, cached for next connect (2nd and subsequent), assigned by first outgoing connection
UINT64 CreatedTime; // Creation date and time UINT64 CreatedTime; // Creation date and time
UINT64 LastCommTime; // Last communication date and time UINT64 LastCommTime; // Last communication date and time

View File

@ -13116,7 +13116,6 @@ SOCK *ListenEx63(UINT port, bool local_only, bool enable_ca, IP *listen_ip)
#ifdef OS_WIN32 #ifdef OS_WIN32
if (enable_ca) if (enable_ca)
{ {
setsockopt(s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, (char *)&true_flag, sizeof(true_flag));
backlog = 1; backlog = 1;
} }
#endif #endif
@ -13642,6 +13641,62 @@ int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool
} }
} }
#else #else
#if 0
LPSTR PrintError(int ErrorCode)
{
static char Message[1024];
// If this program was multithreaded, we'd want to use
// FORMAT_MESSAGE_ALLOCATE_BUFFER instead of a static buffer here.
// (And of course, free the buffer when we were done with it)
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, ErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)Message, 1024, NULL);
return Message;
}
#else
char *PrintError(int ErrorCode)
{
char *Message;
switch (ErrorCode) {
case WSAEFAULT:
Message = "Bad address.";
break;
case WSAEWOULDBLOCK:
Message = "Resource temporarily unavailable.";
break;
case WSAEINPROGRESS:
Message = "Operation now in progress.";
break;
case WSAEALREADY:
Message = "Operation already in progress.";
break;
case WSAEAFNOSUPPORT:
Message = "Address family not supported by protocol family.";
break;
case WSAEADDRINUSE:
Message = "Address already in use.";
break;
case WSAEADDRNOTAVAIL:
Message = "Cannot assign requested address.";
break;
default:
Message = "";
break;
}
return Message;
}
#endif
// Connection with timeout (Win32 version) // Connection with timeout (Win32 version)
int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag) int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag)
{ {
@ -13773,8 +13828,71 @@ void SetSockHighPriority(SOCK *s, bool flag)
SetSockTos(s, (flag ? 16 : 0)); SetSockTos(s, (flag ? 16 : 0));
} }
// Bind the socket to IPv4 or IPV6 address
int bind_sock(SOCKET sock, IP *ip, UINT port)
{
//char tmp[MAX_HOST_NAME_LEN + 1];
//memset(tmp, 0, sizeof(tmp));
//IPToStr(tmp, sizeof(tmp), ip);
//Debug("bind_sock(): Binding... IP address %s:%d\n", tmp, port);
if (IsIP4(ip))
{
// Declare variables
struct sockaddr_in sockaddr_in;
Zero(&sockaddr_in, sizeof(sockaddr_in));
// Set up the sockaddr structure
sockaddr_in.sin_family = AF_INET;
IPToInAddr(&sockaddr_in.sin_addr, ip);
sockaddr_in.sin_port = htons((USHORT)port);
//inet_pton(AF_INET, tmp, &addr_in.sin_addr.s_addr);
UINT true_flag = 1;
// This only have enabled for UNIX system since there is a bug
// in the implementation of REUSEADDR in Windows OS
(void)setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&true_flag, sizeof(true_flag));
// Bind the socket using the information in the sockaddr structure
return (bind(sock, (struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in)));
}
else
{
// Declare variables
struct sockaddr_in6 sockaddr_in;
Zero(&sockaddr_in, sizeof(sockaddr_in));
// Set up the sockaddr structure
sockaddr_in.sin6_family = AF_INET6;
IPToInAddr6(&sockaddr_in.sin6_addr, ip);
sockaddr_in.sin6_scope_id = ip->ipv6_scope_id;
sockaddr_in.sin6_port = htons((USHORT)port);
//inet_pton(AF_INET6, tmp, &sockaddr_in.sin6_addr.s6_bytes);
UINT true_flag = 1;
#ifdef OS_UNIX
// It is necessary to set the IPv6 Only flag on a UNIX system
(void)setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &true_flag, sizeof(true_flag));
#endif // OS_UNIX
// This only have enabled for UNIX system since there is a bug
// in the implementation of REUSEADDR in Windows OS
(void)setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&true_flag, sizeof(true_flag));
// Bind the socket using the information in the sockaddr structure
return (bind(sock, (struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in)));
}
}
// Connect to the IPv4 host using a socket // Connect to the IPv4 host using a socket
SOCKET ConnectTimeoutIPv4(IP* ip, UINT port, UINT timeout, bool* cancel_flag) SOCKET ConnectTimeoutIPv4(IP* ip, UINT port, UINT timeout, bool* cancel_flag)
{
return BindConnectTimeoutIPv4(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, ip, port, timeout, cancel_flag);
}
// Connect to the IPv4 host using a socket
SOCKET BindConnectTimeoutIPv4(IP* localIP, UINT localport, IP* ip, UINT port, UINT timeout, bool* cancel_flag)
{ {
SOCKET s; SOCKET s;
struct sockaddr_in sockaddr4; struct sockaddr_in sockaddr4;
@ -13791,6 +13909,34 @@ SOCKET ConnectTimeoutIPv4(IP *ip, UINT port, UINT timeout, bool *cancel_flag)
// Socket creation // Socket creation
s = socket(AF_INET, SOCK_STREAM, 0); s = socket(AF_INET, SOCK_STREAM, 0);
// Top of Bind outgoing connection
if (s != INVALID_SOCKET) {
int ier;
IP tmpIP;
if (localIP == BIND_LOCALIP_NULL) {
StrToIP(&tmpIP, "0.0.0.0"); // A NULL address for the argument "localIP" is treated as if "0::0" in IPV4 was specified.
localIP = &tmpIP;
}
if ((IsZeroIP(localIP) == false) || (localport != 0)) {
// Bind the socket
if (bind_sock(s, localIP, localport) != 0) {
#ifdef OS_WIN32
ier = WSAGetLastError();
Debug("IPv4 bind() failed with error: %d %s\n", ier, PrintError(ier));
#else
Debug("IPv4 bind() failed with error: %d %s\n", errno, strerror(errno));
#endif
closesocket(s);
s = INVALID_SOCKET;
}
}
}
// Bottom of Bind outgoing connection
if (s != INVALID_SOCKET) if (s != INVALID_SOCKET)
{ {
// Connection // Connection
@ -14054,6 +14200,20 @@ void ConnectThreadForRUDP(THREAD *thread, void *param)
// IPv4 connection thread (multiple protocols, multiple addresses) // IPv4 connection thread (multiple protocols, multiple addresses)
void ConnectThreadForIPv4(THREAD* thread, void* param) void ConnectThreadForIPv4(THREAD* thread, void* param)
{
CONNECT_SERIAL_PARAM* p = (CONNECT_SERIAL_PARAM*)param;
if (thread == NULL || p == NULL)
{
return;
}
p->LocalIP = BIND_LOCALIP_NULL;
p->LocalPort = BIND_LOCALPORT_NULL;
return BindConnectThreadForIPv4(thread, param);
}
// IPv4 connection thread (multiple protocols, multiple addresses)
//void ConnectThreadForIPv4(THREAD* thread, void* param)
void BindConnectThreadForIPv4(THREAD *thread, void *param)
{ {
SOCKET s = INVALID_SOCKET; SOCKET s = INVALID_SOCKET;
IP current_ip; IP current_ip;
@ -14106,7 +14266,8 @@ void ConnectThreadForIPv4(THREAD *thread, void *param)
if (use_natt == false) if (use_natt == false)
{ {
// Normal connection without using NAT-T // Normal connection without using NAT-T
s = ConnectTimeoutIPv4(ip, p->Port, p->Timeout, p->CancelFlag); // s = ConnectTimeoutIPv4(ip, p->Port, p->Timeout, p->CancelFlag);
s = BindConnectTimeoutIPv4(p->LocalIP, p->LocalPort, ip, p->Port, p->Timeout, p->CancelFlag);
if (s != INVALID_SOCKET) if (s != INVALID_SOCKET)
{ {
@ -14409,6 +14570,20 @@ void ConnectThreadForIPv4(THREAD *thread, void *param)
// IPv6 connection thread (multiple addresses) // IPv6 connection thread (multiple addresses)
void ConnectThreadForIPv6(THREAD* thread, void* param) void ConnectThreadForIPv6(THREAD* thread, void* param)
{
CONNECT_SERIAL_PARAM* p = (CONNECT_SERIAL_PARAM*)param;
if (thread == NULL || p == NULL)
{
return;
}
p->LocalIP = BIND_LOCALIP_NULL;
p->LocalPort = BIND_LOCALPORT_NULL;
return BindConnectThreadForIPv6(thread, param);
}
// IPv6 connection thread (multiple addresses)
//void ConnectThreadForIPv6(THREAD *thread, void *param)
void BindConnectThreadForIPv6(THREAD* thread, void* param)
{ {
SOCKET s = INVALID_SOCKET; SOCKET s = INVALID_SOCKET;
IP current_ip; IP current_ip;
@ -14463,6 +14638,34 @@ void ConnectThreadForIPv6(THREAD *thread, void *param)
// Socket creation // Socket creation
s = socket(AF_INET6, SOCK_STREAM, 0); s = socket(AF_INET6, SOCK_STREAM, 0);
// Top of Bind outgoing connection
if (s != INVALID_SOCKET){
int ier;
IP tmpIP;
if (p->LocalIP == BIND_LOCALIP_NULL) {
StrToIP(&tmpIP, "0::0"); // A NULL address for the argument "p->LocalIP" is treated as if "0::0" in IPV6 was specified.
p->LocalIP = &tmpIP;
}
if ((IsZeroIP(p->LocalIP) == false) || (p->LocalPort != 0)){
// Bind the socket
if (bind_sock(s, p->LocalIP, p->LocalPort) != 0) {
#ifdef OS_WIN32
ier = WSAGetLastError();
Debug("IPv6 bind() failed with error: %d %s\n", ier, PrintError(ier));
#else
Debug("IPv6 bind() failed with error: %d %s\n", errno, strerror(errno));
#endif
closesocket(s);
s = INVALID_SOCKET;
}
}
}
// Bottom of Bind outgoing connection
if (s != INVALID_SOCKET) if (s != INVALID_SOCKET)
{ {
// Connection // Connection
@ -14588,6 +14791,18 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
return ConnectEx5(hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, NULL, NULL, NULL, ret_ip); return ConnectEx5(hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, NULL, NULL, NULL, ret_ip);
} }
SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip) SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip)
{
return BindConnectEx5(BIND_LOCALIP_NULL, BIND_LOCALPORT_NULL, hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, ssl_option, ssl_err, hint_str, ret_ip);
}
//SOCK* ConnectEx4(char* hostname, UINT port, UINT timeout, bool* cancel_flag, char* nat_t_svc_name, UINT* nat_t_error_code, bool try_start_ssl, bool no_get_hostname, IP* ret_ip)
SOCK *BindConnectEx4(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, IP *ret_ip)
{
// return ConnectEx5(hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, NULL, NULL, NULL, ret_ip);
return BindConnectEx5(localIP, localport, hostname, port, timeout, cancel_flag, nat_t_svc_name, nat_t_error_code, try_start_ssl, no_get_hostname, NULL, NULL, NULL, ret_ip);
}
//SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip)
SOCK *BindConnectEx5(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip)
{ {
bool dummy = false; bool dummy = false;
bool use_natt = false; bool use_natt = false;
@ -14683,6 +14898,16 @@ SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
if (LIST_NUM(iplist_v6) > 0) if (LIST_NUM(iplist_v6) > 0)
{ {
p6.IpList = iplist_v6; p6.IpList = iplist_v6;
if (localIP == BIND_LOCALIP_NULL) {
p6.LocalIP = BIND_LOCALIP_NULL; // Make the NULL address passing through
}
else {
CopyIP(&p6.LocalIP_Cache, localIP);
p6.LocalIP = &p6.LocalIP_Cache;
}
p6.LocalPort = localport;
p6.Port = port; p6.Port = port;
p6.Timeout = timeout; p6.Timeout = timeout;
StrCpy(p6.Hostname, sizeof(p6.Hostname), hostname); StrCpy(p6.Hostname, sizeof(p6.Hostname), hostname);
@ -14696,13 +14921,24 @@ SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
p6.Ret_Ip = &ret_ip6; p6.Ret_Ip = &ret_ip6;
p6.RetryDelay = 250; p6.RetryDelay = 250;
p6.Delay = 0; p6.Delay = 0;
t6 = NewThread(ConnectThreadForIPv6, &p6); // t6 = NewThread(ConnectThreadForIPv6, &p6);
t6 = NewThread(BindConnectThreadForIPv6, &p6); // For binding a socket
} }
// IPv4 connection thread // IPv4 connection thread
if (LIST_NUM(iplist_v4) > 0) if (LIST_NUM(iplist_v4) > 0)
{ {
p4.IpList = iplist_v4; p4.IpList = iplist_v4;
if (localIP == BIND_LOCALIP_NULL) {
p4.LocalIP = BIND_LOCALIP_NULL; // Make the NULL address passing through
}
else {
CopyIP(&p4.LocalIP_Cache, localIP);
p4.LocalIP = &p4.LocalIP_Cache;
}
p4.LocalPort = localport;
p4.Port = port; p4.Port = port;
p4.Timeout = timeout; p4.Timeout = timeout;
StrCpy(p4.Hostname, sizeof(p4.Hostname), hostname); StrCpy(p4.Hostname, sizeof(p4.Hostname), hostname);
@ -14721,7 +14957,8 @@ SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
p4.Ret_Ip = &ret_ip4; p4.Ret_Ip = &ret_ip4;
p4.RetryDelay = 250; p4.RetryDelay = 250;
p4.Delay = 250; // Delay by 250ms to prioritize IPv6 (RFC 6555 recommends 150-250ms, Chrome uses 300ms) p4.Delay = 250; // Delay by 250ms to prioritize IPv6 (RFC 6555 recommends 150-250ms, Chrome uses 300ms)
t4 = NewThread(ConnectThreadForIPv4, &p4); // t4 = NewThread(ConnectThreadForIPv4, &p4);
t4 = NewThread(BindConnectThreadForIPv4, &p4); // For binding a socket
} }
if (t6 == NULL || t4 == NULL) if (t6 == NULL || t4 == NULL)

View File

@ -812,6 +812,9 @@ struct RUDP_STACK
struct CONNECT_SERIAL_PARAM struct CONNECT_SERIAL_PARAM
{ {
LIST *IpList; LIST *IpList;
UINT LocalPort; // Local port number to bind
IP *LocalIP; // Local IP address to bind. NULL address allowed to use.
IP LocalIP_Cache; // Local IP address to bind
UINT Port; UINT Port;
UINT Timeout; UINT Timeout;
char Hostname[MAX_SIZE]; char Hostname[MAX_SIZE];
@ -950,6 +953,10 @@ void ConnectThreadForRUDP(THREAD *thread, void *param);
void ConnectThreadForOverDnsOrIcmp(THREAD *thread, void *param); void ConnectThreadForOverDnsOrIcmp(THREAD *thread, void *param);
void ConnectThreadForIPv4(THREAD *thread, void *param); void ConnectThreadForIPv4(THREAD *thread, void *param);
void ConnectThreadForIPv6(THREAD *thread, void *param); void ConnectThreadForIPv6(THREAD *thread, void *param);
void BindConnectThreadForIPv4(THREAD *thread, void *param);
void BindConnectThreadForIPv6(THREAD *thread, void *param);
SOCK *CreateTCPSock(SOCKET s, bool is_ipv6, IP *current_ip, bool no_get_hostname, char *hostname_original); SOCK *CreateTCPSock(SOCKET s, bool is_ipv6, IP *current_ip, bool no_get_hostname, char *hostname_original);
SOCK *NewRUDPClientNatT(char *svc_name, IP *ip, UINT *error_code, UINT timeout, bool *cancel, char *hint_str, char *target_hostname); SOCK *NewRUDPClientNatT(char *svc_name, IP *ip, UINT *error_code, UINT timeout, bool *cancel, char *hint_str, char *target_hostname);
RUDP_STACK *NewRUDPServer(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode, volatile UINT *natt_global_udp_port, UCHAR rand_port_id, IP *listen_ip); RUDP_STACK *NewRUDPServer(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode, volatile UINT *natt_global_udp_port, UCHAR rand_port_id, IP *listen_ip);
@ -1113,6 +1120,14 @@ SOCK *ConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, IP *ret_ip); SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, IP *ret_ip);
SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip); SOCK *ConnectEx5(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip);
SOCKET ConnectTimeoutIPv4(IP *ip, UINT port, UINT timeout, bool *cancel_flag); SOCKET ConnectTimeoutIPv4(IP *ip, UINT port, UINT timeout, bool *cancel_flag);
// New function named with prefix "Bind" binds outgoing connection to a specific address. New one is wrapped in original one.
#define BIND_LOCALIP_NULL NULL // NULL IP address specifies no binding
#define BIND_LOCALPORT_NULL 0 // NULL port number specifies no binding
SOCK *BindConnectEx4(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, IP *ret_ip);
SOCK *BindConnectEx5(IP *localIP, UINT localport, char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool no_get_hostname, SSL_VERIFY_OPTION *ssl_option, UINT *ssl_err, char *hint_str, IP *ret_ip);
SOCKET BindConnectTimeoutIPv4(IP *localIP, UINT localport, IP *ip, UINT port, UINT timeout, bool *cancel_flag);
bool SetSocketBufferSize(SOCKET s, bool send, UINT size); bool SetSocketBufferSize(SOCKET s, bool send, UINT size);
UINT SetSocketBufferSizeWithBestEffort(SOCKET s, bool send, UINT size); UINT SetSocketBufferSizeWithBestEffort(SOCKET s, bool send, UINT size);
void InitUdpSocketBufferSize(SOCKET s); void InitUdpSocketBufferSize(SOCKET s);

View File

@ -16,11 +16,25 @@ SOCK *Internal_ProxyTcpConnect(PROXY_PARAM_IN *param, volatile bool *cancel_flag
} }
#endif #endif
return ConnectEx4(param->Hostname, param->Port, param->Timeout, (bool *)cancel_flag, NULL, NULL, false, true, resolved_ip); //return ConnectEx4(param->Hostname, param->Port, param->Timeout, (bool*)cancel_flag, NULL, NULL, false, true, resolved_ip);
return BindConnectEx4(param->BindLocalIP, param->BindLocalPort, param->Hostname, param->Port, param->Timeout, (bool *)cancel_flag, NULL, NULL, false, true, resolved_ip);
} }
// Connect to an HTTP proxy // Connect to an HTTP proxy
UINT ProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag) UINT ProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag)
{
// Validate arguments
if (out == NULL || in == NULL || in->Port == 0 || in->TargetPort == 0 || IsEmptyStr(in->Hostname) || IsEmptyStr(in->TargetHostname))
{
return PROXY_ERROR_PARAMETER;
}
in->BindLocalIP = BIND_LOCALIP_NULL;
in->BindLocalPort = BIND_LOCALPORT_NULL;
return BindProxyHttpConnect(out, in, cancel_flag);
}
// Connect to an HTTP proxy
UINT BindProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag)
{ {
bool dummy_cancel_flag = false, use_auth = false; bool dummy_cancel_flag = false, use_auth = false;
char target_hostname[MAX_HOST_NAME_LEN + 1]; char target_hostname[MAX_HOST_NAME_LEN + 1];
@ -208,6 +222,19 @@ FAILURE:
// Connect to a SOCKS5 proxy (RFC1928, RFC1929 defines username/password authentication) // Connect to a SOCKS5 proxy (RFC1928, RFC1929 defines username/password authentication)
UINT ProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag) UINT ProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag)
{
// Validate arguments
if (out == NULL || in == NULL || in->Port == 0 || in->TargetPort == 0 || IsEmptyStr(in->Hostname) || IsEmptyStr(in->TargetHostname))
{
return PROXY_ERROR_PARAMETER;
}
in->BindLocalIP = BIND_LOCALIP_NULL;
in->BindLocalPort = BIND_LOCALPORT_NULL;
return BindProxySocks5Connect(out, in, cancel_flag);
}
// Connect to a SOCKS5 proxy (RFC1928, RFC1929 defines username/password authentication)
UINT BindProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag)
{ {
bool dummy_cancel_flag = false; bool dummy_cancel_flag = false;
UCHAR tmp, recv_buf[2], *recv_buf_final; UCHAR tmp, recv_buf[2], *recv_buf_final;
@ -521,6 +548,19 @@ FAILURE:
// Connect to a SOCKS4 proxy // Connect to a SOCKS4 proxy
UINT ProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag) UINT ProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag)
{
// Validate arguments
if (out == NULL || in == NULL || in->Port == 0 || in->TargetPort == 0 || IsEmptyStr(in->Hostname) || IsEmptyStr(in->TargetHostname))
{
return PROXY_ERROR_PARAMETER;
}
in->BindLocalIP = BIND_LOCALIP_NULL;
in->BindLocalPort = BIND_LOCALPORT_NULL;
return BindProxySocks4Connect(out, in, cancel_flag);
}
// Connect to a SOCKS4 proxy
UINT BindProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag)
{ {
bool dummy_cancel_flag = false; bool dummy_cancel_flag = false;
UCHAR tmp, recv_buf[8]; UCHAR tmp, recv_buf[8];

View File

@ -30,6 +30,8 @@ struct PROXY_PARAM_IN
UINT Timeout; UINT Timeout;
char HttpCustomHeader[HTTP_CUSTOM_HEADER_MAX_SIZE]; char HttpCustomHeader[HTTP_CUSTOM_HEADER_MAX_SIZE];
char HttpUserAgent[HTTP_HEADER_USER_AGENT_MAX_SIZE + 1]; char HttpUserAgent[HTTP_HEADER_USER_AGENT_MAX_SIZE + 1];
IP *BindLocalIP; // Source IP address for outgoing connection
UINT BindLocalPort; // UINT used not USHORT // Source port number for outgoing connection
#ifdef OS_WIN32 #ifdef OS_WIN32
void *Hwnd; void *Hwnd;
#endif #endif
@ -45,4 +47,9 @@ UINT ProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *c
UINT ProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag); UINT ProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag);
UINT ProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag); UINT ProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag);
// New function named with prefix "Bind" binds outgoing connection to a specific address. New one is wrapped in original one.
UINT BindProxyHttpConnect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag);
UINT BindProxySocks5Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag);
UINT BindProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool *cancel_flag);
#endif #endif

View File

@ -13,7 +13,7 @@
#undef APSTUDIO_READONLY_SYMBOLS #undef APSTUDIO_READONLY_SYMBOLS
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// 日文 resources // 、鬢・resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN) #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
#ifdef _WIN32 #ifdef _WIN32
@ -1654,10 +1654,14 @@ BEGIN
LTEXT "@S_MODE",S_MODE,254,169,166,17 LTEXT "@S_MODE",S_MODE,254,169,166,17
CONTROL "@R_BRIDGE",R_BRIDGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,191,166,9 CONTROL "@R_BRIDGE",R_BRIDGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,191,166,9
CONTROL "@R_MONITOR",R_MONITOR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,205,166,9 CONTROL "@R_MONITOR",R_MONITOR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,254,205,166,9
GROUPBOX "@STATIC17",IDC_STATIC,222,225,205,30 GROUPBOX "@STATIC17", IDC_STATIC, 222, 225, 205, 43
CONTROL "@R_NO_ROUTING",R_NO_ROUTING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,233,238,181,9 CONTROL "@R_NO_ROUTING",R_NO_ROUTING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,233,234,181,9
ICON ICO_WARNING,S_WARNING_ICON,223,261,18,18 LTEXT "@STATIC20", IDC_STATIC, 233, 243, 58, 17
LTEXT "@STATIC18",IDC_STATIC,247,261,180,26 EDITTEXT E_BIND_LOCALIP, 292, 243, 126, 11, ES_RIGHT | ES_AUTOHSCROLL
LTEXT "@STATIC21", IDC_STATIC, 233, 255, 58, 12
EDITTEXT E_BIND_LOCALPORT, 292, 255, 40, 11, ES_RIGHT | ES_AUTOHSCROLL
ICON ICO_WARNING,S_WARNING_ICON,223,270,18,18
LTEXT "@STATIC18",IDC_STATIC,247,270,180,26
DEFPUSHBUTTON "@IDOK",IDOK,294,291,64,15 DEFPUSHBUTTON "@IDOK",IDOK,294,291,64,15
PUSHBUTTON "@IDCANCEL",IDCANCEL,363,291,64,15 PUSHBUTTON "@IDCANCEL",IDCANCEL,363,291,64,15
ICON ICO_SWITCH,IDC_STATIC,230,169,18,18 ICON ICO_SWITCH,IDC_STATIC,230,169,18,18
@ -4865,12 +4869,12 @@ END
// //
BIN_WINPCAP BIN "Dummy.bin" BIN_WINPCAP BIN "Dummy.bin"
#endif // 日文 resources #endif // 、鬢・resources
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// 中文 (台灣) resources // 、、、・(・xニW) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHT) #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHT)
#ifdef _WIN32 #ifdef _WIN32
@ -4886,12 +4890,12 @@ LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL
// Icon with lowest ID value placed first to ensure application icon // Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems. // remains consistent on all systems.
ICO_LANG_TRADITIONAL_CHINESE ICON "LANG_TRADITIONAL_CHINESE.ico" ICO_LANG_TRADITIONAL_CHINESE ICON "LANG_TRADITIONAL_CHINESE.ico"
#endif // 中文 (台灣) resources #endif // 、、、・(・xニW) resources
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// 英文 (美國) resources // ュ^、・(ャ・・ resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32 #ifdef _WIN32
@ -4952,7 +4956,7 @@ BMP_ZURUKKO BITMAP "Zurukko.bmp"
BMP_VPNGATEEN BITMAP "VPNGateEN.bmp" BMP_VPNGATEEN BITMAP "VPNGateEN.bmp"
BMP_VPNGATEJA BITMAP "VPNGateJA.bmp" BMP_VPNGATEJA BITMAP "VPNGateJA.bmp"
BMP_UNIVTSUKUBA BITMAP "UnivTsukuba.bmp" BMP_UNIVTSUKUBA BITMAP "UnivTsukuba.bmp"
#endif // 英文 (美國) resources #endif // ュ^、・(ャ・・ resources
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////

View File

@ -339,6 +339,8 @@
#define C_NUM_TCP 1075 #define C_NUM_TCP 1075
#define B_TRUST 1076 #define B_TRUST 1076
#define E_INTERVAL 1076 #define E_INTERVAL 1076
#define E_BIND_LOCALIP 9076 // Bind source IP address
#define E_BIND_LOCALPORT 9077 // Bind source port number
#define B_PROXY_CONFIG 1077 #define B_PROXY_CONFIG 1077
#define B_SERVER_CERT 1078 #define B_SERVER_CERT 1078
#define B_VIEW_SERVER_CERT 1079 #define B_VIEW_SERVER_CERT 1079

View File

@ -2421,6 +2421,8 @@ STATIC17 Other Confi&gurations:
R_NO_ROUTING No Adjustments of &Routing Table R_NO_ROUTING No Adjustments of &Routing Table
STATIC18 Keep the settings default in this dialog unless you are told to do so by a system administrator, or you have expertise for networking and security. STATIC18 Keep the settings default in this dialog unless you are told to do so by a system administrator, or you have expertise for networking and security.
STATIC19 The VoIP / QoS functions handle high priority packets such as IP telephone packets (VoIP) to be transmitted faster. STATIC19 The VoIP / QoS functions handle high priority packets such as IP telephone packets (VoIP) to be transmitted faster.
STATIC20 Source IP Address:
STATIC21 Source Port Number:
R_DISABLE_QOS Disable VoIP / &QoS Functions R_DISABLE_QOS Disable VoIP / &QoS Functions
IDOK &OK IDOK &OK
IDCANCEL Cancel IDCANCEL Cancel

View File

@ -2424,6 +2424,8 @@ STATIC17 その他の設定(&G):
R_NO_ROUTING ルーティングテーブルの調整処理を行わない(&R) R_NO_ROUTING ルーティングテーブルの調整処理を行わない(&R)
STATIC18 この設定画面の設定項目は、システム管理者から指示があった場合や、ネットワークやセキュリティに関して詳しい知識をお持ちの場合以外は変更しないでください。 STATIC18 この設定画面の設定項目は、システム管理者から指示があった場合や、ネットワークやセキュリティに関して詳しい知識をお持ちの場合以外は変更しないでください。
STATIC19 VoIP / QoS 対応機能を使用すると、IP 電話パケットなどの優先度の高いパケットを VPN 内で高速に伝送できます。 STATIC19 VoIP / QoS 対応機能を使用すると、IP 電話パケットなどの優先度の高いパケットを VPN 内で高速に伝送できます。
STATIC20 送信元IPアドレス:
STATIC21 送信元ポート番号:
R_DISABLE_QOS VoIP / QoS 対応機能を無効にする(&Q) R_DISABLE_QOS VoIP / QoS 対応機能を無効にする(&Q)
IDOK &OK IDOK &OK
IDCANCEL キャンセル IDCANCEL キャンセル