├── README.md └── server_target.c /README.md: -------------------------------------------------------------------------------- 1 | # socks5 2 | reverse proxy server 3 | -------------------------------------------------------------------------------- /server_target.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define SOCK5_VER_ID 0x05 9 | #define SOCK5_METHOD_NO_AUTH_REQUIRED 0x00 10 | 11 | #define MAX_BUFFER 512 12 | #define MAX_METHODS 255 13 | 14 | #define SOCK5_MAX_DMN_NAME_LEN 0xFF 15 | 16 | 17 | struct sock_ver_id_msg { 18 | uint8_t ver; 19 | uint8_t nmethods; 20 | uint8_t methods[MAX_METHODS]; 21 | }; 22 | 23 | struct sock_method_sel_msg { 24 | uint8_t ver; 25 | uint8_t method; 26 | }; 27 | 28 | struct sock5_dmn_name { 29 | uint8_t len; 30 | char name[SOCK5_MAX_DMN_NAME_LEN]; 31 | }; 32 | 33 | struct sock5_msg { 34 | uint8_t ver; 35 | union { 36 | uint8_t cmd; 37 | uint8_t rep; 38 | }; 39 | uint8_t rsv; 40 | uint8_t atyp; 41 | union { 42 | uint8_t ipv4_addr[4]; 43 | uint8_t ipv6_addr[16]; 44 | struct sock5_dmn_name dmn_name; 45 | }; 46 | uint16_t dst_port; 47 | }; 48 | 49 | int recv_buf(SOCKET s, void *buf, uint32_t count) 50 | { 51 | while (count) { 52 | int to_recv, rcvd; 53 | to_recv = count < MAX_BUFFER ? 54 | count : MAX_BUFFER; 55 | if ((rcvd = recv(s, buf, to_recv, 0)) == INVALID_SOCKET || rcvd == 0) 56 | return 0; 57 | buf = (char *)buf + rcvd; 58 | count -= rcvd; 59 | } 60 | return 1; 61 | } 62 | 63 | int send_buf(SOCKET s, void *buf, uint32_t count) 64 | { 65 | while (count) { 66 | uint32_t to_send, sent; 67 | to_send = count < MAX_BUFFER ? count : MAX_BUFFER; 68 | if ((sent = send(s, buf, to_send, 0)) == SOCKET_ERROR) 69 | return 0; 70 | buf = (char *)buf + sent; 71 | count -= sent; 72 | } 73 | return 1; 74 | } 75 | 76 | static int find_method(uint8_t *methods, uint8_t count, uint8_t method_type) 77 | { 78 | while (count--) 79 | if (*methods++ == method_type) 80 | return 1; 81 | return 0; 82 | } 83 | 84 | static int sock5_negotiate(SOCKET s) 85 | { 86 | struct sock_ver_id_msg sid; 87 | struct sock_method_sel_msg sm; 88 | int res; 89 | 90 | res = 0; 91 | if (!recv_buf(s, &sid, offsetof(struct sock_ver_id_msg, methods))) 92 | goto cleanup; 93 | if (!recv_buf(s, sid.methods, sid.nmethods)) 94 | goto cleanup; 95 | if (sid.ver != SOCK5_VER_ID) 96 | goto cleanup; 97 | if (!find_method(sid.methods, sid.nmethods, SOCK5_METHOD_NO_AUTH_REQUIRED)) 98 | goto cleanup; 99 | sm.ver = SOCK5_VER_ID; 100 | sm.method = SOCK5_METHOD_NO_AUTH_REQUIRED; 101 | if (!send_buf(s, &sm, sizeof(sm))) 102 | goto cleanup; 103 | res = 1; 104 | cleanup: 105 | return res; 106 | } 107 | 108 | #define SOCK5_ADDR_TYPE_IPV4 0x01 109 | #define SOCK5_ADDR_TYPE_DNAME 0x03 110 | #define SOCK5_ADDR_TYPE_IPV6 0x04 111 | 112 | static int sock5_recv_request(SOCKET s, struct sock5_msg *req) 113 | { 114 | int res; 115 | if (!recv_buf(s, req, offsetof(struct sock5_msg, dmn_name))) 116 | return 0; 117 | switch (req->atyp) { 118 | case SOCK5_ADDR_TYPE_IPV4: 119 | res = recv_buf(s, req->ipv4_addr, sizeof(req->ipv4_addr)); 120 | break; 121 | case SOCK5_ADDR_TYPE_DNAME: 122 | if (!recv_buf(s, &req->dmn_name.len, sizeof(req->dmn_name.len))) 123 | return 0; 124 | res = recv_buf(s, &req->dmn_name.name, req->dmn_name.len); 125 | break; 126 | case SOCK5_ADDR_TYPE_IPV6: 127 | res = recv_buf(s, req->ipv6_addr, sizeof(req->ipv6_addr)); 128 | break; 129 | default: 130 | return 0; 131 | } 132 | if (!res) 133 | return 0; 134 | return recv_buf(s, &req->dst_port, sizeof(req->dst_port)); 135 | } 136 | 137 | static int sock5_send_reply(SOCKET s, struct sock5_msg *reply) 138 | { 139 | int res; 140 | if (!send_buf(s, reply, offsetof(struct sock5_msg, dmn_name))) 141 | return 0; 142 | switch (reply->atyp) { 143 | case SOCK5_ADDR_TYPE_IPV4: 144 | res = send_buf(s, reply->ipv4_addr, sizeof(reply->ipv4_addr)); 145 | break; 146 | case SOCK5_ADDR_TYPE_DNAME: 147 | if (!send_buf(s, &reply->dmn_name.len, sizeof(reply->dmn_name.len))) 148 | return 0; 149 | res = send_buf(s, reply->dmn_name.name, reply->dmn_name.len); 150 | break; 151 | case SOCK5_ADDR_TYPE_IPV6: 152 | res = send_buf(s, reply->ipv6_addr, sizeof(reply->ipv6_addr)); 153 | break; 154 | default: 155 | return 0; 156 | } 157 | if (!res) 158 | return 0; 159 | return send_buf(s, &reply->dst_port, sizeof(reply->dst_port)); 160 | } 161 | 162 | #define SOCK5_CMND_CONNECT 0x01 163 | 164 | #define SOCK5_REPLY_SUCCESS 0x00 165 | #define SOCK5_REPLY_GEN_ERROR 0x01 166 | 167 | static int create_tunnel(uint8_t ipv4_addr[4], uint16_t port, SOCKET *s) 168 | { 169 | SOCKET sockfd; 170 | struct sockaddr_in service; 171 | if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) 172 | return 0; 173 | 174 | service.sin_family = AF_INET; 175 | memcpy(&service.sin_addr.S_un.S_un_b, ipv4_addr, 4); 176 | service.sin_port = port; 177 | if (connect(sockfd, (struct sockaddr *)&service, sizeof(service)) == SOCKET_ERROR) 178 | return 0; 179 | 180 | *s = sockfd; 181 | return 1; 182 | } 183 | 184 | DWORD WINAPI sock_thread(void *param) 185 | { 186 | SOCKET ls, rs; 187 | struct sock5_msg req; 188 | struct sock5_msg reply; 189 | fd_set sfd_set; 190 | printf("******************--------------------------------******************\n"); 191 | ls = (SOCKET)param; 192 | rs = INVALID_SOCKET; 193 | /* negotiate */ 194 | if (!sock5_negotiate(ls)) 195 | goto cleanup; 196 | /* get request */ 197 | if (!sock5_recv_request(ls, &req)) 198 | goto cleanup; 199 | reply = req; 200 | reply.rep = (req.cmd == SOCK5_CMND_CONNECT) && create_tunnel(req.ipv4_addr, req.dst_port, &rs) ? 201 | SOCK5_REPLY_SUCCESS : SOCK5_REPLY_GEN_ERROR; 202 | if (!sock5_send_reply(ls, &reply)) 203 | goto cleanup; 204 | if (reply.rep != SOCK5_REPLY_SUCCESS) 205 | goto cleanup; /* MUST be terminated, RFC1928, page 6 */ 206 | 207 | /* tunnel */ 208 | FD_ZERO(&sfd_set); 209 | while (1) { 210 | char buf[MAX_BUFFER]; 211 | int recvd; 212 | SOCKET src, dest; 213 | 214 | /* reset them again since select clears the flag for 215 | * the descriptor that isn't ready 216 | */ 217 | FD_SET(ls, &sfd_set); 218 | FD_SET(rs, &sfd_set); 219 | if (select(0, &sfd_set, NULL, NULL, NULL) == SOCKET_ERROR) 220 | goto cleanup; 221 | src = FD_ISSET(ls, &sfd_set) ? ls : rs; 222 | dest = src == ls ? rs : ls; 223 | if ((recvd = recv(src, buf, sizeof(buf), 0)) <= 0) 224 | goto cleanup; 225 | if (!send_buf(dest, buf, recvd)) 226 | goto cleanup; 227 | } 228 | cleanup: 229 | if (rs != INVALID_SOCKET) 230 | closesocket(rs); 231 | closesocket(ls); 232 | ExitThread(0); 233 | return 0; 234 | } 235 | 236 | static int create_sock_thread(SOCKET s) 237 | { 238 | HANDLE handle; 239 | if (!(handle = CreateThread(NULL, 0, sock_thread, (void *)s, 0, 0))) 240 | return 0; 241 | CloseHandle(handle); 242 | 243 | return 1; 244 | } 245 | 246 | static int listener_run(USHORT port) 247 | { 248 | struct sockaddr_in service; 249 | SOCKET sockfd; 250 | 251 | if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) 252 | return 0; 253 | service.sin_family = AF_INET; 254 | service.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); 255 | service.sin_port = htons(port); 256 | if (bind(sockfd, (struct sockaddr *)&service, sizeof(service)) == SOCKET_ERROR) { 257 | closesocket(sockfd); 258 | return 0; 259 | } 260 | if (listen(sockfd, SOMAXCONN)) 261 | return 1; 262 | while (1) { 263 | SOCKET new_fd; 264 | new_fd = accept(sockfd, NULL, NULL); 265 | if (new_fd != INVALID_SOCKET) { 266 | printf("connection accepted\n"); 267 | create_sock_thread(new_fd); 268 | } 269 | } 270 | } 271 | 272 | static int init_winsock2(void) 273 | { 274 | WORD ver; 275 | WSADATA wd; 276 | ver = MAKEWORD(2, 2); 277 | return WSAStartup(ver, &wd) == 0; 278 | } 279 | 280 | int main(void) 281 | { 282 | int port = 8080; 283 | struct sockaddr_in service; 284 | SOCKET sockfd; 285 | int con_sock; 286 | 287 | if (!init_winsock2()) 288 | return 1; 289 | 290 | //printf("insert the port number\n"); 291 | //scanf("%d", &port); 292 | //listener_run(port); 293 | /*Edit*/ 294 | if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) 295 | return 0; 296 | service.sin_family = AF_INET; 297 | service.sin_addr.S_un.S_addr = inet_addr("192.168.21.10"); 298 | service.sin_port = htons(port); 299 | printf("Here\n"); 300 | con_sock = connect(sockfd, (struct sockaddr *)&service, sizeof(service)); 301 | if(con_sock == SOCKET_ERROR){ 302 | printf("connect failed\n"); 303 | return 0; 304 | } 305 | create_sock_thread(con_sock); 306 | printf("connect succedded\n"); 307 | /*Edit*/ 308 | WSACleanup(); 309 | } 310 | --------------------------------------------------------------------------------