Пример #1
0
// SOCKS Proxy support
static enum proxy_status proxy_connect(struct host *h, const char *target_host,
 int target_port)
{
  struct addrinfo target_hints, *target_ais, *target_ai;
  char port_str[6];
  int ret;

  snprintf(port_str, 6, "%d", target_port);
  port_str[5] = 0;

  memset(&target_hints, 0, sizeof(struct addrinfo));
  target_hints.ai_socktype = (h->proto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM;
  target_hints.ai_protocol = h->proto;
  target_hints.ai_family = h->af;
  ret = dns_getaddrinfo(target_host, port_str, &target_hints, &target_ais,
   h->timeout_ms);

  /* Some perimeter gateways block access to DNS [wifi hotspots are
   * particularly notorious for this] so we have to fall back to SOCKS4a
   * to force the proxy to DNS the address for us. If this fails, we abort.
   */
  if(ret != 0)
    return socks4a_connect(h, target_host, target_port);

#ifdef CONFIG_IPV6
  for(target_ai = target_ais; target_ai; target_ai = target_ai->ai_next)
  {
    if(target_ai->ai_family != AF_INET6)
      continue;
    if (socks5_connect(h, target_ai) == PROXY_SUCCESS)
    {
      platform_freeaddrinfo(target_ais);
      return PROXY_SUCCESS;
    }
  }
#endif

  for(target_ai = target_ais; target_ai; target_ai = target_ai->ai_next)
  {
    if(target_ai->ai_family != AF_INET)
      continue;
    if (socks5_connect(h, target_ai) == PROXY_SUCCESS)
    {
      platform_freeaddrinfo(target_ais);
      return PROXY_SUCCESS;
    }
    if (socks4_connect(h, target_ai) == PROXY_SUCCESS)
    {
      platform_freeaddrinfo(target_ais);
      return PROXY_SUCCESS;
    }
  }

  return PROXY_CONNECTION_FAILED;
}
Пример #2
0
/*
 * Setup a Tor connection meaning initiating the initial SOCKS5 handshake.
 *
 * Return 0 on success else a negative value.
 */
static int setup_tor_connection(struct connection *conn)
{
	int ret;

	assert(conn);

	DBG("Setting up a connection to the Tor network on fd %d", conn->fd);

	ret = socks5_connect(conn);
	if (ret < 0) {
		goto error;
	}

	ret = socks5_send_method(conn);
	if (ret < 0) {
		goto error;
	}

	ret = socks5_recv_method(conn);
	if (ret < 0) {
		goto error;
	}

error:
	return ret;
}
Пример #3
0
int handle_socks(int fd, struct sockaddr_in addr, char *host, int portnum)
{
	struct sockaddr_in proxy;
	struct hostent *hp;
                
	memset(&proxy, 0, sizeof(proxy));
	if (!(hp = gethostbyname(host)))
	{
		bitchsay("Unable to resolve SOCKS proxy host address: %s", host);
		return -1;
	}
	bcopy(hp->h_addr, (char *)&proxy.sin_addr, hp->h_length);
	proxy.sin_family = AF_INET;
	proxy.sin_port = htons(portnum);
	alarm(get_int_var(CONNECT_TIMEOUT_VAR));
	if (connect(fd, (struct sockaddr *)&proxy, sizeof(proxy)) < 0)
	{
		alarm(0);
		bitchsay("Unable to connect to SOCKS5 proxy: %s", strerror(errno));
		close(fd);
		return -1;
	}
	alarm(0);
	if (!socks5_connect(fd, portnum, &addr))
	{
		close(fd);
		if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
		{
			bitchsay("Unable to get socket: %s", strerror(errno));
			return -1;
		}
		alarm(get_int_var(CONNECT_TIMEOUT_VAR));
		if (connect(fd, (struct sockaddr *)&proxy, sizeof(proxy)) < 0)
		{
			alarm(0);
			bitchsay("Unable to connect to SOCKS4 proxy: %s", strerror(errno));
			return -1;
		}
		alarm(0);
		if (!socks4_connect(fd, portnum, &addr))
		{
			close(fd);
			return -1;
		}
	}
	return fd;
}
Пример #4
0
jb_socket connect_to_forward(struct client_state *csp, struct forward_spec *fwd, int is_proxy) {
    csp->fwd = fwd;
    const char *dest_host;
    int dest_port;
    /* Figure out if we need to connect to the web server or a HTTP proxy. */
    if (fwd->forward_host)
    {
        /* HTTP proxy */
        dest_host = fwd->forward_host;
        dest_port = fwd->forward_port;
    }
    else
    {
        /* Web server */
        dest_host = csp->http->host;
        dest_port = csp->http->port;
    }

    /* Connect, maybe using a SOCKS proxy */
    switch (fwd->type)
    {
        case SOCKS_NONE:
        case FORWARD_WEBSERVER:
            return connect_to(dest_host, dest_port, csp, is_proxy);
            break;
        case SOCKS_4:
        case SOCKS_4A:
            return socks4_connect(fwd->gateway_host, fwd->gateway_port, fwd->type, dest_host, dest_port, csp);
            break;
        case SOCKS_5:
        case SOCKS_5T:
            return socks5_connect(fwd->gateway_host, fwd->gateway_port, fwd->type, dest_host, dest_port, csp);
            break;
        default:
            log_error(LOG_LEVEL_FATAL,
                      "Internal error in rfc2553_connect_to() ip. Bad proxy type: %d", fwd->type);
            return JB_INVALID_SOCKET;
    }
}
Пример #5
0
gint socks_connect(SockInfo *sock, const gchar *hostname, gushort port,
		   SocksInfo *socks_info)
{
	g_return_val_if_fail(sock != NULL, -1);
	g_return_val_if_fail(hostname != NULL, -1);
	g_return_val_if_fail(socks_info != NULL, -1);

	debug_print("socks_connect: connect to %s:%u via %s:%u\n",
		    hostname, port,
		    socks_info->proxy_host, socks_info->proxy_port);

	if (socks_info->type == SOCKS_SOCKS5)
		return socks5_connect(sock, hostname, port,
				      socks_info->proxy_name,
				      socks_info->proxy_pass);
	else if (socks_info->type == SOCKS_SOCKS4)
		return socks4_connect(sock, hostname, port);
	else
		g_warning("socks_connect: unknown SOCKS type: %d\n",
			  socks_info->type);

	return -1;
}
Пример #6
0
int
socks5_negotiate(int clisock, struct conndesc *conn)
{
	u_int i;
	char hostname[256];
	u_char nmethods, len, junk; 
	struct sockaddr_in rem_in;
	struct socks5_req req5;
	struct socks5_v_repl rep5;
	struct hostent *hent;	
	
	req5.vn = 5;
	req5.rsv = 0;
	
	/*
	 * Start by retrieving number of methods, version number has
	 * already been consumed by the calling procedure
	 */

	if (atomicio(read, clisock, &nmethods, 1) != 1) {
		warnv(1, "read()");
		return (-1);
	}

	/* Eat up methods */

	i = 0;
	while (i++ < nmethods) 
		if (atomicio(read, clisock, &junk, 1) != 1) {
			warnv(1, "read()");
			return (-1);
		}

	/*
	 * We don't support any authentication methods yet, so simply
	 * ignore it and send reply with no authentication required.
	 */

	rep5.ver = 5;
	rep5.res = 0;

	if (atomicio(write, clisock, &rep5, 2) != 2) {
		warnv(1, "write()");
		return (-1);
	}

	/* Receive data up to atyp */
	if (atomicio(read, clisock, &req5, 4) != 4) {
		warnv(1, "read()");
		return (-1);
	}
	if (req5.vn != 5)
		return (-1);

	memset(&rem_in, 0, sizeof(rem_in));

	switch (req5.atyp) {
	case SOCKS5_ATYP_IPV4:
		if (atomicio(read, clisock, &req5.destaddr, 4) != 4) {
			warnv(1, "read()");
			return (-1);
		}
		rem_in.sin_family = AF_INET;
		rem_in.sin_addr.s_addr = req5.destaddr;
		break;
	case SOCKS5_ATYP_FQDN:
		if (atomicio(read, clisock, &len, 1) != 1) {
			warnv(1, "read()");
			return (-1);
		}
		if (atomicio(read, clisock, hostname, len) != len) {
			warnv(1, "read()");
			return (-1);
		}
		hostname[len] = '\0';
		if ((hent = gethostbyname(hostname)) == NULL) {
			/* XXX no hstrerror() on solaris */
#ifndef __sun__			
			warnxv(1, "gethostbyname(): %s", hstrerror(h_errno));
#endif /* __sun__ */
			return (-1);
		}
		rem_in.sin_family = AF_INET;
		rem_in.sin_addr = *(struct in_addr *)hent->h_addr;
		break;
	default:
		return (-1);
	}

	if (atomicio(read, clisock, &req5.destport, 2) != 2) {
		warnv(1, "read()");
		return (-1);
	}

	rem_in.sin_port = req5.destport;

	/*
	 * Now we have a filled in in_addr for the target host:
	 * target_in, no socket yet.  This is provided by the command
	 * specific functions multiplexed in the next switch
	 * statement.
	 */

	switch (req5.cd) {
	case SOCKS5_CD_CONNECT:
		return (socks5_connect(clisock, &rem_in, &req5, conn));
	case SOCKS5_CD_BIND:
	        signal_setup();
	        event_dispatch();
		return (socks5_bind(clisock, &rem_in, &req5));
	case SOCKS5_CD_UDP_ASSOC:
	default:
		return (-1);
	}
}