client: added socks5 proxy support
AG: - move creation info members to end of struct - add LWS_WITH_SOCKS5 CMake var, defaults to OFF - cast away some warnings about signed / unsigned in strncpy Signed-off-by: Andy Ning <andy.ning@windriver.com>
This commit is contained in:
parent
8f16f92cac
commit
ed92b6dfe7
8 changed files with 516 additions and 5 deletions
|
@ -118,6 +118,7 @@ option(LWS_FALLBACK_GETHOSTBYNAME "Also try to do dns resolution using gethostby
|
|||
option(LWS_WITH_ZIP_FOPS "Support serving pre-zipped files" ON)
|
||||
option(LWS_AVOID_SIGPIPE_IGN "Android 7+ seems to need this" OFF)
|
||||
option(LWS_WITH_STATS "Keep statistics of lws internal operations" OFF)
|
||||
option(LWS_WITH_SOCKS5 "Allow use of SOCKS5 proxy on client connections" OFF)
|
||||
|
||||
if (LWS_WITH_LWSWS)
|
||||
message(STATUS "LWS_WITH_LWSWS --> Enabling LWS_WITH_PLUGINS and LWS_WITH_LIBUV")
|
||||
|
@ -1770,6 +1771,7 @@ message(" LWS_WITH_ESP32 = ${LWS_WITH_ESP32}")
|
|||
message(" LWS_WITH_ZIP_FOPS = ${LWS_WITH_ZIP_FOPS}")
|
||||
message(" LWS_AVOID_SIGPIPE_IGN = ${LWS_AVOID_SIGPIPE_IGN}")
|
||||
message(" LWS_WITH_STATS = ${LWS_WITH_STATS}")
|
||||
message(" LWS_WITH_SOCKS5 = ${LWS_WITH_SOCKS5}")
|
||||
|
||||
message("---------------------------------------------------------------------")
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ lws_client_connect_2(struct lws *wsi)
|
|||
|
||||
/* proxy? */
|
||||
|
||||
/* http proxy */
|
||||
if (wsi->vhost->http_proxy_port) {
|
||||
plen = sprintf((char *)pt->serv_buf,
|
||||
"CONNECT %s:%u HTTP/1.0\x0d\x0a"
|
||||
|
@ -49,7 +50,26 @@ lws_client_connect_2(struct lws *wsi)
|
|||
#endif
|
||||
server_addr4.sin_port = htons(wsi->vhost->http_proxy_port);
|
||||
|
||||
} else {
|
||||
}
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
/* socks proxy */
|
||||
else if (wsi->vhost->socks_proxy_port) {
|
||||
socks_generate_msg(wsi, SOCKS_MSG_GREETING, (size_t *)&plen);
|
||||
lwsl_client("%s\n", "Sending SOCKS Greeting.");
|
||||
|
||||
ads = wsi->vhost->socks_proxy_address;
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(wsi->vhost)) {
|
||||
memset(&server_addr6, 0, sizeof(struct sockaddr_in6));
|
||||
server_addr6.sin6_port = htons(wsi->vhost->socks_proxy_port);
|
||||
} else
|
||||
#endif
|
||||
server_addr4.sin_port = htons(wsi->vhost->socks_proxy_port);
|
||||
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(wsi->vhost)) {
|
||||
|
@ -275,6 +295,7 @@ lws_client_connect_2(struct lws *wsi)
|
|||
|
||||
/* we are connected to server, or proxy */
|
||||
|
||||
/* http proxy */
|
||||
if (wsi->vhost->http_proxy_port) {
|
||||
|
||||
/*
|
||||
|
@ -303,6 +324,26 @@ lws_client_connect_2(struct lws *wsi)
|
|||
|
||||
return wsi;
|
||||
}
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
/* socks proxy */
|
||||
else if (wsi->vhost->socks_proxy_port) {
|
||||
n = send(wsi->desc.sockfd, (char *)pt->serv_buf, plen,
|
||||
MSG_NOSIGNAL);
|
||||
if (n < 0) {
|
||||
lwsl_debug("ERROR writing greeting to socks proxy"
|
||||
"socket.\n");
|
||||
cce = "socks write failed";
|
||||
goto failed;
|
||||
}
|
||||
|
||||
lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SOCKS_GREETING_REPLY,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
wsi->mode = LWSCM_WSCL_WAITING_SOCKS_GREETING_REPLY;
|
||||
|
||||
return wsi;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* provoke service to issue the handshake directly
|
||||
|
@ -754,7 +795,10 @@ lws_client_connect_via_info2(struct lws *wsi)
|
|||
stash->method))
|
||||
goto bail1;
|
||||
|
||||
lws_free_set_NULL(wsi->u.hdr.stash);
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
if (!wsi->vhost->socks_proxy_port)
|
||||
lws_free_set_NULL(wsi->u.hdr.stash);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check with each extension if it is able to route and proxy this
|
||||
|
@ -782,7 +826,10 @@ lws_client_connect_via_info2(struct lws *wsi)
|
|||
return lws_client_connect_2(wsi);
|
||||
|
||||
bail1:
|
||||
lws_free_set_NULL(wsi->u.hdr.stash);
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
if (!wsi->vhost->socks_proxy_port)
|
||||
lws_free_set_NULL(wsi->u.hdr.stash);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -836,3 +883,73 @@ lws_client_connect(struct lws_context *context, const char *address,
|
|||
return lws_client_connect_via_info(&i);
|
||||
}
|
||||
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
void socks_generate_msg(struct lws *wsi, enum socks_msg_type type,
|
||||
size_t *msg_len)
|
||||
{
|
||||
struct lws_context *context = wsi->context;
|
||||
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
||||
size_t len = 0;
|
||||
|
||||
if (type == SOCKS_MSG_GREETING) {
|
||||
/* socks version, version 5 only */
|
||||
pt->serv_buf[len++] = SOCKS_VERSION_5;
|
||||
/* number of methods */
|
||||
pt->serv_buf[len++] = 2;
|
||||
/* username password method */
|
||||
pt->serv_buf[len++] = SOCKS_AUTH_USERNAME_PASSWORD;
|
||||
/* no authentication method */
|
||||
pt->serv_buf[len++] = SOCKS_AUTH_NO_AUTH;
|
||||
}
|
||||
else if (type == SOCKS_MSG_USERNAME_PASSWORD) {
|
||||
size_t user_len = 0;
|
||||
size_t passwd_len = 0;
|
||||
|
||||
user_len = strlen(wsi->vhost->socks_user);
|
||||
passwd_len = strlen(wsi->vhost->socks_password);
|
||||
|
||||
/* the subnegotiation version */
|
||||
pt->serv_buf[len++] = SOCKS_SUBNEGOTIATION_VERSION_1;
|
||||
/* length of the user name */
|
||||
pt->serv_buf[len++] = user_len;
|
||||
/* user name */
|
||||
strncpy((char *)&pt->serv_buf[len], wsi->vhost->socks_user,
|
||||
context->pt_serv_buf_size - len);
|
||||
len += user_len;
|
||||
/* length of the password */
|
||||
pt->serv_buf[len++] = passwd_len;
|
||||
/* password */
|
||||
strncpy((char *)&pt->serv_buf[len], wsi->vhost->socks_password,
|
||||
context->pt_serv_buf_size - len);
|
||||
len += passwd_len;
|
||||
}
|
||||
else if (type == SOCKS_MSG_CONNECT) {
|
||||
size_t len_index = 0;
|
||||
short net_num = 0;
|
||||
char *net_buf = (char*)&net_num;
|
||||
|
||||
/* socks version */
|
||||
pt->serv_buf[len++] = SOCKS_VERSION_5;
|
||||
/* socks command */
|
||||
pt->serv_buf[len++] = SOCKS_COMMAND_CONNECT;
|
||||
/* reserved */
|
||||
pt->serv_buf[len++] = 0;
|
||||
/* address type */
|
||||
pt->serv_buf[len++] = SOCKS_ATYP_DOMAINNAME;
|
||||
len_index = len;
|
||||
len++;
|
||||
/* the address we tell SOCKS proxy to connect to */
|
||||
strncpy((char *)&(pt->serv_buf[len]), wsi->u.hdr.stash->address,
|
||||
context->pt_serv_buf_size - len);
|
||||
len += strlen(wsi->u.hdr.stash->address);
|
||||
net_num = htons((short)wsi->c_port);
|
||||
/* the port we tell SOCKS proxy to connect to */
|
||||
pt->serv_buf[len++] = net_buf[0];
|
||||
pt->serv_buf[len++] = net_buf[1];
|
||||
/* the length of the address, excluding port */
|
||||
pt->serv_buf[len_index] = strlen(wsi->u.hdr.stash->address);
|
||||
}
|
||||
|
||||
*msg_len = len;
|
||||
}
|
||||
#endif
|
||||
|
|
197
lib/client.c
197
lib/client.c
|
@ -81,7 +81,10 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi,
|
|||
const char *cce = NULL;
|
||||
unsigned char c;
|
||||
char *sb = p;
|
||||
int n, len;
|
||||
int n = 0, len = 0;
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
char conn_mode = 0, pending_timeout = 0;
|
||||
#endif
|
||||
|
||||
switch (wsi->mode) {
|
||||
|
||||
|
@ -101,6 +104,195 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi,
|
|||
/* either still pending connection, or changed mode */
|
||||
return 0;
|
||||
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
/* SOCKS Greeting Reply */
|
||||
case LWSCM_WSCL_WAITING_SOCKS_GREETING_REPLY:
|
||||
|
||||
/* handle proxy hung up on us */
|
||||
|
||||
if (pollfd->revents & LWS_POLLHUP) {
|
||||
|
||||
lwsl_warn("SOCKS connection %p (fd=%d) dead\n",
|
||||
(void *)wsi, pollfd->fd);
|
||||
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
|
||||
if (n < 0) {
|
||||
if (LWS_ERRNO == LWS_EAGAIN) {
|
||||
lwsl_debug("SOCKS read returned EAGAIN..."
|
||||
"retrying\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
lwsl_err("ERROR reading from SOCKS socket\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* processing greeting reply */
|
||||
if (pt->serv_buf[0] == SOCKS_VERSION_5
|
||||
&& pt->serv_buf[1] == SOCKS_AUTH_NO_AUTH)
|
||||
{
|
||||
lwsl_client("%s\n", "SOCKS greeting reply received "
|
||||
"- No Authentication Method");
|
||||
socks_generate_msg(wsi, SOCKS_MSG_CONNECT, (size_t *)&len);
|
||||
|
||||
conn_mode = LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY;
|
||||
pending_timeout = PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY;
|
||||
lwsl_client("%s\n", "Sending SOCKS connect command");
|
||||
}
|
||||
else if (pt->serv_buf[0] == SOCKS_VERSION_5
|
||||
&& pt->serv_buf[1] == SOCKS_AUTH_USERNAME_PASSWORD)
|
||||
{
|
||||
lwsl_client("%s\n", "SOCKS greeting reply received "
|
||||
"- User Name Password Method");
|
||||
socks_generate_msg(wsi, SOCKS_MSG_USERNAME_PASSWORD,
|
||||
(size_t *)&len);
|
||||
|
||||
conn_mode = LWSCM_WSCL_WAITING_SOCKS_AUTH_REPLY;
|
||||
pending_timeout = PENDING_TIMEOUT_AWAITING_SOCKS_AUTH_REPLY;
|
||||
lwsl_client("%s\n", "Sending SOCKS user/password");
|
||||
}
|
||||
else
|
||||
{
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
lwsl_err("ERROR SOCKS greeting reply failed, method "
|
||||
"code: %d\n", pt->serv_buf[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = send(wsi->desc.sockfd, (char *)pt->serv_buf, len,
|
||||
MSG_NOSIGNAL);
|
||||
if (n < 0) {
|
||||
lwsl_debug("ERROR writing socks command to socks proxy "
|
||||
"socket\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lws_set_timeout(wsi, pending_timeout, AWAITING_TIMEOUT);
|
||||
wsi->mode = conn_mode;
|
||||
|
||||
break;
|
||||
/* SOCKS auth Reply */
|
||||
case LWSCM_WSCL_WAITING_SOCKS_AUTH_REPLY:
|
||||
|
||||
/* handle proxy hung up on us */
|
||||
|
||||
if (pollfd->revents & LWS_POLLHUP) {
|
||||
|
||||
lwsl_warn("SOCKS connection %p (fd=%d) dead\n",
|
||||
(void *)wsi, pollfd->fd);
|
||||
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
|
||||
if (n < 0) {
|
||||
if (LWS_ERRNO == LWS_EAGAIN) {
|
||||
lwsl_debug("SOCKS read returned EAGAIN... "
|
||||
"retrying\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
lwsl_err("ERROR reading from socks socket\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* processing auth reply */
|
||||
if (pt->serv_buf[0] == SOCKS_SUBNEGOTIATION_VERSION_1
|
||||
&& pt->serv_buf[1] == SOCKS_SUBNEGOTIATION_STATUS_SUCCESS)
|
||||
{
|
||||
lwsl_client("%s\n", "SOCKS password reply recieved - "
|
||||
"successful");
|
||||
socks_generate_msg(wsi, SOCKS_MSG_CONNECT, (size_t *)&len);
|
||||
|
||||
conn_mode = LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY;
|
||||
pending_timeout =
|
||||
PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY;
|
||||
lwsl_client("%s\n", "Sending SOCKS connect command");
|
||||
}
|
||||
else
|
||||
{
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
lwsl_err("ERROR : SOCKS user/password reply failed, "
|
||||
"error code: %d\n", pt->serv_buf[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = send(wsi->desc.sockfd, (char *)pt->serv_buf, len,
|
||||
MSG_NOSIGNAL);
|
||||
if (n < 0) {
|
||||
lwsl_debug("ERROR writing connect command to SOCKS "
|
||||
"socket\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lws_set_timeout(wsi, pending_timeout, AWAITING_TIMEOUT);
|
||||
wsi->mode = conn_mode;
|
||||
|
||||
break;
|
||||
|
||||
/* SOCKS connect command Reply */
|
||||
case LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY:
|
||||
|
||||
/* handle proxy hung up on us */
|
||||
|
||||
if (pollfd->revents & LWS_POLLHUP) {
|
||||
|
||||
lwsl_warn("SOCKS connection %p (fd=%d) dead\n",
|
||||
(void *)wsi, pollfd->fd);
|
||||
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
|
||||
if (n < 0) {
|
||||
if (LWS_ERRNO == LWS_EAGAIN) {
|
||||
lwsl_debug("SOCKS read returned EAGAIN... "
|
||||
"retrying\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
lwsl_err("ERROR reading from socks socket\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* processing connect reply */
|
||||
if (pt->serv_buf[0] == SOCKS_VERSION_5
|
||||
&& pt->serv_buf[1] == SOCKS_REQUEST_REPLY_SUCCESS)
|
||||
{
|
||||
lwsl_client("%s\n", "SOCKS connect reply recieved - "
|
||||
"successful");
|
||||
}
|
||||
else
|
||||
{
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
lwsl_err("ERROR SOCKS connect reply failed, error "
|
||||
"code: %d\n", pt->serv_buf[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* free stash since we are done with it */
|
||||
lws_free_set_NULL(wsi->u.hdr.stash);
|
||||
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
|
||||
wsi->vhost->socks_proxy_address))
|
||||
goto bail3;
|
||||
wsi->c_port = wsi->vhost->socks_proxy_port;
|
||||
|
||||
/* clear his proxy connection timeout */
|
||||
|
||||
lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
||||
|
||||
goto start_ws_hanshake;
|
||||
#endif
|
||||
case LWSCM_WSCL_WAITING_PROXY_REPLY:
|
||||
|
||||
/* handle proxy hung up on us */
|
||||
|
@ -149,6 +341,9 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi,
|
|||
* take care of our lws_callback_on_writable
|
||||
* happening at a time when there's no real connection yet
|
||||
*/
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
start_ws_hanshake:
|
||||
#endif
|
||||
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
|
||||
return -1;
|
||||
|
||||
|
|
|
@ -497,9 +497,14 @@ lws_create_vhost(struct lws_context *context,
|
|||
#if !defined(LWS_WITH_ESP8266)
|
||||
vh->http_proxy_port = 0;
|
||||
vh->http_proxy_address[0] = '\0';
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
vh->socks_proxy_port = 0;
|
||||
vh->socks_proxy_address[0] = '\0';
|
||||
#endif
|
||||
|
||||
/* either use proxy from info, or try get it from env var */
|
||||
|
||||
/* http proxy */
|
||||
if (info->http_proxy_address) {
|
||||
/* override for backwards compatibility */
|
||||
if (info->http_proxy_port)
|
||||
|
@ -512,7 +517,23 @@ lws_create_vhost(struct lws_context *context,
|
|||
lws_set_proxy(vh, p);
|
||||
#endif
|
||||
}
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
/* socks proxy */
|
||||
if (info->socks_proxy_address) {
|
||||
/* override for backwards compatibility */
|
||||
if (info->socks_proxy_port)
|
||||
vh->socks_proxy_port = info->socks_proxy_port;
|
||||
lws_set_socks(vh, info->socks_proxy_address);
|
||||
} else {
|
||||
#ifdef LWS_HAVE_GETENV
|
||||
p = getenv("socks_proxy");
|
||||
if (p)
|
||||
lws_set_socks(vh, p);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vh->ka_time = info->ka_time;
|
||||
vh->ka_interval = info->ka_interval;
|
||||
vh->ka_probes = info->ka_probes;
|
||||
|
|
|
@ -1325,6 +1325,79 @@ auth_too_long:
|
|||
return -1;
|
||||
}
|
||||
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
LWS_VISIBLE int
|
||||
lws_set_socks(struct lws_vhost *vhost, const char *socks)
|
||||
{
|
||||
#if !defined(LWS_WITH_ESP8266)
|
||||
char *p_at, *p_colon;
|
||||
char user[96];
|
||||
char password[96];
|
||||
|
||||
if (!socks)
|
||||
return -1;
|
||||
|
||||
vhost->socks_user[0] = '\0';
|
||||
vhost->socks_password[0] = '\0';
|
||||
|
||||
p_at = strchr(socks, '@');
|
||||
if (p_at) { /* auth is around */
|
||||
if ((unsigned int)(p_at - socks) > (sizeof(user)
|
||||
+ sizeof(password) - 2)) {
|
||||
lwsl_err("Socks auth too long\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
p_colon = strchr(socks, ':');
|
||||
if (p_colon) {
|
||||
if ((unsigned int)(p_colon - socks) > (sizeof(user)
|
||||
- 1) ) {
|
||||
lwsl_err("Socks user too long\n");
|
||||
goto bail;
|
||||
}
|
||||
if ((unsigned int)(p_at - p_colon) > (sizeof(password)
|
||||
- 1) ) {
|
||||
lwsl_err("Socks password too long\n");
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
strncpy(vhost->socks_user, socks, p_colon - socks);
|
||||
strncpy(vhost->socks_password, p_colon + 1,
|
||||
p_at - (p_colon + 1));
|
||||
|
||||
lwsl_info(" Socks auth, user: %s, password: %s\n",
|
||||
vhost->socks_user, vhost->socks_password );
|
||||
|
||||
socks = p_at + 1;
|
||||
}
|
||||
|
||||
strncpy(vhost->socks_proxy_address, socks,
|
||||
sizeof(vhost->socks_proxy_address) - 1);
|
||||
vhost->socks_proxy_address[sizeof(vhost->socks_proxy_address) - 1]
|
||||
= '\0';
|
||||
|
||||
p_colon = strchr(vhost->socks_proxy_address, ':');
|
||||
if (!p_colon && !vhost->socks_proxy_port) {
|
||||
lwsl_err("socks_proxy needs to be address:port\n");
|
||||
return -1;
|
||||
} else {
|
||||
if (p_colon) {
|
||||
*p_colon = '\0';
|
||||
vhost->socks_proxy_port = atoi(p_colon + 1);
|
||||
}
|
||||
}
|
||||
|
||||
lwsl_info(" Socks %s:%u\n", vhost->socks_proxy_address,
|
||||
vhost->socks_proxy_port);
|
||||
|
||||
return 0;
|
||||
|
||||
bail:
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
LWS_VISIBLE const struct lws_protocols *
|
||||
lws_get_protocol(struct lws *wsi)
|
||||
{
|
||||
|
|
|
@ -1812,7 +1812,7 @@ struct lws_context_creation_info {
|
|||
/**< VHOST + CONTEXT: 0, or LWS_SERVER_OPTION_... bitfields */
|
||||
void *user;
|
||||
/**< CONTEXT: optional user pointer that can be recovered via the context
|
||||
* pointer using lws_context_user */
|
||||
* pointer using lws_context_user */
|
||||
int ka_time;
|
||||
/**< CONTEXT: 0 for no TCP keepalive, otherwise apply this keepalive
|
||||
* timeout to all libwebsocket sockets, client or server */
|
||||
|
@ -1955,6 +1955,11 @@ struct lws_context_creation_info {
|
|||
*/
|
||||
int simultaneous_ssl_restriction;
|
||||
/**< CONTEXT: 0 (no limit) or limit of simultaneous SSL sessions possible.*/
|
||||
const char *socks_proxy_address;
|
||||
/**< VHOST: If non-NULL, attempts to proxy via the given address.
|
||||
* If proxy auth is required, use format "username:password\@server:port" */
|
||||
unsigned int socks_proxy_port;
|
||||
/**< VHOST: If socks_proxy_address was non-NULL, uses this port */
|
||||
|
||||
/* Add new things just above here ---^
|
||||
* This is part of the ABI, don't needlessly break compatibility
|
||||
|
@ -2070,6 +2075,25 @@ lws_context_is_deprecated(struct lws_context *context);
|
|||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_set_proxy(struct lws_vhost *vhost, const char *proxy);
|
||||
|
||||
/**
|
||||
* lws_set_socks() - Setup socks to lws_context.
|
||||
* \param vhost: pointer to struct lws_vhost you want set socks for
|
||||
* \param socks: pointer to c string containing socks in format address:port
|
||||
*
|
||||
* Returns 0 if socks string was parsed and socks was setup.
|
||||
* Returns -1 if socks is NULL or has incorrect format.
|
||||
*
|
||||
* This is only required if your OS does not provide the socks_proxy
|
||||
* environment variable (eg, OSX)
|
||||
*
|
||||
* IMPORTANT! You should call this function right after creation of the
|
||||
* lws_context and before call to connect. If you call this
|
||||
* function after connect behavior is undefined.
|
||||
* This function will override proxy settings made on lws_context
|
||||
* creation with genenv() call.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_set_socks(struct lws_vhost *vhost, const char *socks);
|
||||
|
||||
struct lws_vhost;
|
||||
|
||||
|
@ -3471,6 +3495,9 @@ enum pending_timeout {
|
|||
PENDING_TIMEOUT_WS_PONG_CHECK_SEND_PING = 16,
|
||||
PENDING_TIMEOUT_WS_PONG_CHECK_GET_PONG = 17,
|
||||
PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD = 18,
|
||||
PENDING_TIMEOUT_AWAITING_SOCKS_GREETING_REPLY = 19,
|
||||
PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY = 20,
|
||||
PENDING_TIMEOUT_AWAITING_SOCKS_AUTH_REPLY = 21,
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
};
|
||||
|
|
|
@ -574,12 +574,75 @@ enum connection_mode {
|
|||
LWSCM_WSCL_WAITING_SERVER_REPLY,
|
||||
LWSCM_WSCL_WAITING_EXTENSION_CONNECT,
|
||||
LWSCM_WSCL_PENDING_CANDIDATE_CHILD,
|
||||
LWSCM_WSCL_WAITING_SOCKS_GREETING_REPLY,
|
||||
LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY,
|
||||
LWSCM_WSCL_WAITING_SOCKS_AUTH_REPLY,
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
|
||||
|
||||
};
|
||||
|
||||
/* enums of socks version */
|
||||
enum socks_version {
|
||||
SOCKS_VERSION_4 = 4,
|
||||
SOCKS_VERSION_5 = 5
|
||||
};
|
||||
|
||||
/* enums of subnegotiation version */
|
||||
enum socks_subnegotiation_version {
|
||||
SOCKS_SUBNEGOTIATION_VERSION_1 = 1,
|
||||
};
|
||||
|
||||
/* enums of socks commands */
|
||||
enum socks_command {
|
||||
SOCKS_COMMAND_CONNECT = 1,
|
||||
SOCKS_COMMAND_BIND = 2,
|
||||
SOCKS_COMMAND_UDP_ASSOCIATE = 3
|
||||
};
|
||||
|
||||
/* enums of socks address type */
|
||||
enum socks_atyp {
|
||||
SOCKS_ATYP_IPV4 = 1,
|
||||
SOCKS_ATYP_DOMAINNAME = 3,
|
||||
SOCKS_ATYP_IPV6 = 4
|
||||
};
|
||||
|
||||
/* enums of socks authentication methods */
|
||||
enum socks_auth_method {
|
||||
SOCKS_AUTH_NO_AUTH = 0,
|
||||
SOCKS_AUTH_GSSAPI = 1,
|
||||
SOCKS_AUTH_USERNAME_PASSWORD = 2
|
||||
};
|
||||
|
||||
/* enums of subnegotiation status */
|
||||
enum socks_subnegotiation_status {
|
||||
SOCKS_SUBNEGOTIATION_STATUS_SUCCESS = 0,
|
||||
};
|
||||
|
||||
/* enums of socks request reply */
|
||||
enum socks_request_reply {
|
||||
SOCKS_REQUEST_REPLY_SUCCESS = 0,
|
||||
SOCKS_REQUEST_REPLY_FAILURE_GENERAL = 1,
|
||||
SOCKS_REQUEST_REPLY_CONNECTION_NOT_ALLOWED = 2,
|
||||
SOCKS_REQUEST_REPLY_NETWORK_UNREACHABLE = 3,
|
||||
SOCKS_REQUEST_REPLY_HOST_UNREACHABLE = 4,
|
||||
SOCKS_REQUEST_REPLY_CONNECTION_REFUSED = 5,
|
||||
SOCKS_REQUEST_REPLY_TTL_EXPIRED = 6,
|
||||
SOCKS_REQUEST_REPLY_COMMAND_NOT_SUPPORTED = 7,
|
||||
SOCKS_REQUEST_REPLY_ATYP_NOT_SUPPORTED = 8
|
||||
};
|
||||
|
||||
/* enums used to generate socks messages */
|
||||
enum socks_msg_type {
|
||||
/* greeting */
|
||||
SOCKS_MSG_GREETING,
|
||||
/* credential, user name and password */
|
||||
SOCKS_MSG_USERNAME_PASSWORD,
|
||||
/* connect command */
|
||||
SOCKS_MSG_CONNECT
|
||||
};
|
||||
|
||||
enum {
|
||||
LWS_RXFLOW_ALLOW = (1 << 0),
|
||||
LWS_RXFLOW_PENDING_CHANGE = (1 << 1),
|
||||
|
@ -774,6 +837,11 @@ struct lws_vhost {
|
|||
#if !defined(LWS_WITH_ESP8266)
|
||||
char http_proxy_address[128];
|
||||
char proxy_basic_auth_token[128];
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
char socks_proxy_address[128];
|
||||
char socks_user[96];
|
||||
char socks_password[96];
|
||||
#endif
|
||||
#endif
|
||||
#if defined(LWS_WITH_ESP8266)
|
||||
/* listen sockets need a place to hang their hat */
|
||||
|
@ -801,6 +869,9 @@ struct lws_vhost {
|
|||
|
||||
int listen_port;
|
||||
unsigned int http_proxy_port;
|
||||
#if defined(LWS_WITH_SOCKS5)
|
||||
unsigned int socks_proxy_port;
|
||||
#endif
|
||||
unsigned int options;
|
||||
int count_protocols;
|
||||
int ka_time;
|
||||
|
@ -2103,6 +2174,10 @@ static inline uint64_t lws_stats_atomic_max(struct lws_context * context,
|
|||
(void)context; (void)pt; (void)index; (void)val; return 0; }
|
||||
#endif
|
||||
|
||||
/* socks */
|
||||
void socks_generate_msg(struct lws *wsi, enum socks_msg_type type,
|
||||
size_t *msg_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -134,6 +134,7 @@
|
|||
#cmakedefine LWS_FALLBACK_GETHOSTBYNAME
|
||||
|
||||
#cmakedefine LWS_WITH_STATS
|
||||
#cmakedefine LWS_WITH_SOCKS5
|
||||
|
||||
/* OpenSSL various APIs */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue