[tcp_transport] - Adds Socks4 proxy transport

- Basic implementation of Socks4 protocol.
- Introduce basic host testing.
This commit is contained in:
Euripedes Rocha
2022-10-05 15:20:39 +02:00
parent a3782377d7
commit d6db90a3cd
23 changed files with 718 additions and 36 deletions

View File

@@ -6,21 +6,33 @@
(See the README.md file in the upper level 'examples' directory for more information about examples.)
The application creates a TCP transport connection and tries to connect to the server with predefined IP address and port number. When a connection is successfully established, the application sends message and waits for the answer. After the server's reply, application prints received reply as ASCII text, waits for 2 seconds and sends another message.
The application creates a TCP connection using `tcp_transport` component and tries to connect to the server with predefined IP address and port number. When a connection is successfully established, the application sends message and waits for the answer. After the server's reply, application prints received reply as ASCII text, waits for 2 seconds and sends another message.
It's possible to enable SOCKS proxy support to make the connection to go through a proxy server.
## How to use example
In order to create TCP server that communicates with TCP TRANSPORT Client example, choose one of the following options.
In order to create TCP server that communicates with TCP TRANSPORT Client example, it's possible to choose some host-side tool or one of the scripts available in the example parent directory.
There are many host-side tools which can be used to interact with the UDP/TCP server/client.
One command line tool is [netcat](http://netcat.sourceforge.net) which can send and receive many kinds of packets.
Note: please replace `192.168.0.167 3333` with desired IPV4/IPV6 address (displayed in monitor console) and port number in the following command.
In addition to those tools, simple Python scripts can be found under sockets/scripts directory. Every script is designed to interact with one of the examples.
In addition to those tools, simple Python scripts can be found under the example parent directory. Every script is designed to interact with one of the examples.
### TCP server using netcat
```
nc -l 192.168.0.167 3333
nc -l 0.0.0.0 -p 3333
```
In this scenario netcat doesn't send any data back. If the python scripts are used to test the monitor shows the message sent from the server.
### Using a proxy server
A simple way of testing the usage of the proxy client on Linux systems is
to use ssh as a proxy:
```
ssh -N -v -D 0.0.0.0:1080 localhost
```
## Hardware Required
@@ -35,12 +47,18 @@ idf.py menuconfig
Set following parameters under Example Configuration Options:
* Set `IPV4 Address` that represents remote host the example will connect to.
* Set `Target server Address` that represents remote host the example will connect to.
* Set `Port` number that represents remote port the example will connect to.
* Set `Target Port` number that represents remote port the example will connect to.
Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details.
### Enabling proxy client
Set `Enable proxy client`
Set `Proxy server address` that represents the proxy server the example will connect to.
Set `Proxy server port` number that represents the proxy server port the example will connect to.
## Build and Flash
Build the project and flash it to the board, then run monitor tool to view serial output:

View File

@@ -1,16 +1,37 @@
menu "Example Configuration"
config EXAMPLE_IPV4_ADDR
string "IPV4 Address"
config EXAMPLE_TARGET_ADDR
string "Target server Address"
default "192.168.0.165"
help
The example will connect to this IPV4 address.
config EXAMPLE_PORT
int "Port"
config EXAMPLE_TARGET_PORT
int "Target server Port"
range 0 65535
default 3333
default 8080
help
The remote port to which the client example will connect to.
config EXAMPLE_ENABLE_PROXY
bool "Enable Proxy client"
default n
help
Use a SOCKS proxy to connect
config EXAMPLE_PROXY_ADDR
string "Proxy server Address"
depends on ENABLE_PROXY
default "192.168.0.1"
help
The example will connect to this proxy address to request connection to target.
config EXAMPLE_PROXY_PORT
int "Proxy server Port"
depends on ENABLE_PROXY
range 0 65535
default 1080
help
The proxy port to which the client example will request connection.
endmenu

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -16,26 +16,44 @@
#include "protocol_examples_common.h"
#include "esp_transport.h"
#include "esp_transport_tcp.h"
#include "esp_transport_socks_proxy.h"
#define TARGET_ADDR CONFIG_EXAMPLE_TARGET_ADDR
#define TARGET_PORT CONFIG_EXAMPLE_TARGET_PORT
#define HOST_IP_ADDR CONFIG_EXAMPLE_IPV4_ADDR
#define PORT CONFIG_EXAMPLE_PORT
#ifdef CONFIG_EXAMPLE_ENABLE_PROXY
#define PROXY_ADDR CONFIG_EXAMPLE_PROXY_ADDR
#define PROXY_PORT CONFIG_EXAMPLE_PROXY_PORT
#endif
static const char *TAG = "tcp_transport_client";
static const char *payload = "Message from ESP32";
static const char *payload = "Message from ESP32\n";
static void tcp_transport_client_task(void *pvParameters)
{
char rx_buffer[128];
char host_ip[] = HOST_IP_ADDR;
esp_transport_handle_t tcp = esp_transport_tcp_init();
while (1) {
if (tcp == NULL) {
ESP_LOGE(TAG, "Error occurred during esp_transport_tcp_init()");
char host_ip[] = TARGET_ADDR;
esp_transport_handle_t transport = esp_transport_tcp_init();
#ifdef CONFIG_EXAMPLE_ENABLE_PROXY
/*
* The socks transport is a composed transport, so we save the previously created
* handler to use it as a parent transport, so our transport is now socks over tcp.
* We could have used the ssl transport as parent and we can use a socks transport as a
* parent to websocket transport.
*
*/
esp_transport_handle_t parent = transport;
esp_transport_socks_proxy_config_t proxy_config = {.port = PROXY_PORT, .address = PROXY_ADDR, .version = SOCKS4};
transport = esp_transport_socks_proxy_init(parent, &proxy_config);
#endif
while (1) {
if (transport == NULL) {
ESP_LOGE(TAG, "Error occurred during esp_transport_proxy_init()");
break;
}
int err = esp_transport_connect(tcp, HOST_IP_ADDR, PORT, -1);
int err = esp_transport_connect(transport, TARGET_ADDR, TARGET_PORT, -1);
if (err != 0) {
ESP_LOGE(TAG, "Client unable to connect: errno %d", errno);
break;
@@ -43,34 +61,43 @@ static void tcp_transport_client_task(void *pvParameters)
ESP_LOGI(TAG, "Successfully connected");
while (1) {
int bytes_written = esp_transport_write(tcp, payload, strlen(payload), 0);
int bytes_written = esp_transport_write(transport, payload, strlen(payload), 0);
if (bytes_written < 0) {
ESP_LOGE(TAG, "Error occurred during sending: esp_transport_write() returned %d, errno %d", bytes_written, errno);
break;
}
int len = esp_transport_read(tcp, rx_buffer, sizeof(rx_buffer) - 1, 0);
int len = esp_transport_read(transport, rx_buffer, sizeof(rx_buffer) - 1, 0);
// Error occurred during receiving
if (len < 0) {
ESP_LOGE(TAG, "recv failed: esp_transport_read() returned %d, errno %d", len, errno);
break;
}
// Data received
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
ESP_LOGI(TAG, "Received %d bytes from %s:", len, host_ip);
ESP_LOGI(TAG, "%s", rx_buffer);
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
ESP_LOGI(TAG, "Received %d bytes from %s:", len, host_ip);
ESP_LOGI(TAG, "Received data : %s", rx_buffer);
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
ESP_LOGE(TAG, "Shutting down TCP and restarting...");
esp_transport_close(tcp);
ESP_LOGE(TAG, "Shutting down transport and restarting...");
esp_transport_close(transport);
}
esp_transport_destroy(tcp);
vTaskDelete(NULL);
esp_transport_destroy(transport);
#ifdef CONFIG_EXAMPLE_ENABLE_PROXY
esp_transport_destroy(parent);
#endif
vTaskDelete(NULL);
}
void app_main(void)
{
esp_log_level_set("transport", ESP_LOG_VERBOSE);
esp_log_level_set("transport_base", ESP_LOG_VERBOSE);
esp_log_level_set("transport_proxy", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());