Пример #1
0
/* return 1 for drop, 0 for retry. */
static int auto_retry_or_drop(redsocks_client * client)
{
	time_t now = redsocks_time(NULL);
	autoproxy_client * aclient = (void*)(client + 1) + client->instance->relay_ss->payload_len;
	
	if (aclient->state == AUTOPROXY_NEW)
	{
		if (now - aclient->time_connect_relay <= CIRCUIT_RESET_SECONDS) 
		{
			on_connection_blocked(client);	
			auto_retry(client, 0);
			return 0; 
		}
	}
	else if ( aclient->state == AUTOPROXY_CONNECTED)
	{
//		if (now - aclient->time_connect_relay <= CIRCUIT_RESET_SECONDS) 
		{
			on_connection_blocked(client);	
			auto_retry(client, 0);
			return 0; 
		}
	}
	
	/* drop */
	return 1;
}
Пример #2
0
/* return 1 for drop, 0 for retry. */
static int auto_retry_or_drop(redsocks_client * client)
{
	time_t now = redsocks_time(NULL);
	socks5_client *socks5 = (void*)(client + 1);
	
	if (client->state == socks5_pre_detect)
	{
		if (now - socks5->time_connect_relay <= CIRCUIT_RESET_SECONDS) 
		{
			auto_retry(client, 1);
			return 0; 
		}
	}
	if ( client->state == socks5_direct)
	{
//		if (now - socks5->time_connect_relay <= CIRCUIT_RESET_SECONDS) 
		{
			auto_retry(client, 0);
			return 0; 
		}
	}
	
	/* drop */
	return 1;
}
Пример #3
0
static void auto_event_error(struct bufferevent *buffev, short what, void *_arg)
{
	redsocks_client *client = _arg;
	int saved_errno = errno;
	assert(buffev == client->relay || buffev == client->client);
		
	redsocks_touch_client(client);
			
	redsocks_log_errno(client, LOG_DEBUG, "Errno: %d, State: %d, what: %x", saved_errno, client->state, what);
	if (buffev == client->relay)
	{
		if ( client->state == socks5_pre_detect 
		&& what == (EVBUFFER_WRITE|EVBUFFER_TIMEOUT))
		{
			/* In case timeout occurs for connecting relay, we try to connect
			to target with SOCKS5 proxy. It is possible that the connection to
			target can be set up a bit longer than the timeout value we set. 
			However, it is still better to make connection via proxy. */
			auto_retry(client, 1);
			return;
		}

		if (client->state == socks5_pre_detect  && saved_errno == ECONNRESET)
			if (!auto_retry_or_drop(client))
				return;

		if (client->state == socks5_direct && what == (EVBUFFER_READ|EVBUFFER_ERROR) 
				&& saved_errno == ECONNRESET )
		{
			if (!auto_retry_or_drop(client))
				return;
		}
	}	

	if (what == (EVBUFFER_READ|EVBUFFER_EOF)) {
		struct bufferevent *antiev;
		if (buffev == client->relay)
			antiev = client->client;
		else
			antiev = client->relay;
			
		redsocks_shutdown(client, buffev, SHUT_RD);
		
		if (antiev != NULL && EVBUFFER_LENGTH(antiev->output) == 0)
			redsocks_shutdown(client, antiev, SHUT_WR);
	}
	else {
		
		/*
		myerrno = red_socket_geterrno(buffev);
		redsocks_log_errno(client, LOG_NOTICE, "%s error, code " event_fmt_str,
				buffev == client->relay ? "relay" : "client",
				event_fmt(what));
		*/
		redsocks_drop_client(client);
	}
}																		
Пример #4
0
static void auto_event_error(struct bufferevent *buffev, short what, void *_arg)
{
	redsocks_client *client = _arg;
	autoproxy_client * aclient = (void*)(client + 1) + client->instance->relay_ss->payload_len;
	int saved_errno = errno;
	assert(buffev == client->relay || buffev == client->client);
		
	redsocks_touch_client(client);
			
	redsocks_log_errno(client, LOG_DEBUG, "%s errno(%d), State: %d, what: " event_fmt_str, 
							buffev == client->client?"client":"relay",
							saved_errno, aclient->state, event_fmt(what));
	if (buffev == client->relay)
	{
		
		if ( aclient->state == AUTOPROXY_NEW 
		&& what == (EVBUFFER_WRITE|EVBUFFER_TIMEOUT))
		{
			on_connection_blocked(client);	
			/* In case timeout occurs while connecting relay, we try to connect
			to target via SOCKS5 proxy. It is possible that the connection to
			target can be set up a bit longer than the timeout value we set. 
			However, it is still better to make connection via proxy. */
			auto_retry(client, 1);
			return;
		}

		if (aclient->state == AUTOPROXY_NEW  && saved_errno == ECONNRESET)
			if (!auto_retry_or_drop(client))
				return;

		if (aclient->state == AUTOPROXY_CONNECTED && what == (EVBUFFER_READ|EVBUFFER_ERROR) 
				&& saved_errno == ECONNRESET )
		{
			if (!auto_retry_or_drop(client))
				return;
		}
	}	

	if (what == (EVBUFFER_READ|EVBUFFER_EOF)) {
		struct bufferevent *antiev;
		if (buffev == client->relay)
			antiev = client->client;
		else
			antiev = client->relay;
			
		redsocks_shutdown(client, buffev, SHUT_RD);
		
		if (antiev != NULL && EVBUFFER_LENGTH(antiev->output) == 0)
			redsocks_shutdown(client, antiev, SHUT_WR);
	}
	else {
		redsocks_drop_client(client);
	}
}																		
Пример #5
0
static void auto_connect_relay(redsocks_client *client)
{
	autoproxy_client * aclient = (void*)(client + 1) + client->instance->relay_ss->payload_len;
	struct timeval tv;
	tv.tv_sec = client->instance->config.timeout;
	tv.tv_usec = 0;
	time_t * acc_time = NULL;
	time_t now = redsocks_time(NULL); 	

	/* use default timeout if timeout is not configured */
	if (tv.tv_sec == 0)
		tv.tv_sec = DEFAULT_CONNECT_TIMEOUT_SECONDS; 
	
	if (aclient->state == AUTOPROXY_NEW)
	{
		acc_time = get_addr_time_in_cache(&client->destaddr);
		if (acc_time)
		{
			if (now - *acc_time < CACHE_ITEM_STALE_SECONDS )
			{
				redsocks_log_error(client, LOG_DEBUG, "Found dest IP in cache");

				auto_retry(client, 0);
				return ;
			}
			else
			{
				/* stale this address in cache */
				del_addr_from_cache(&client->destaddr);
				/* update timeout value for quick detection */
				tv.tv_sec = QUICK_CONNECT_TIMEOUT_SECONDS;
			}
		}
		/* connect to target directly without going through proxy */	
		client->relay = red_connect_relay2(&client->destaddr,
						auto_relay_connected, auto_event_error, client, 
						&tv);
	
		aclient->time_connect_relay = redsocks_time(NULL);
	       
		if (!client->relay) {
			redsocks_log_errno(client, LOG_ERR, "auto_connect_relay");
			redsocks_drop_client(client);
		}
	}
	else
	{
		redsocks_log_errno(client, LOG_ERR, "invalid state: %d", aclient->state);
	}
}