mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 22:51:17 +07:00
PY-50689: WSL proxy.
Windows firewall blocks access from WSL by default. This proxy make reverse connection (Win --> Lin). See README.txt for more info GitOrigin-RevId: 2f181faa7c66aee7e766daf007c03877612597be
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b8c732c2b3
commit
719ee22a13
BIN
bin/win/wslproxy
Normal file
BIN
bin/win/wslproxy
Normal file
Binary file not shown.
8
native/WslProxy/CMakeLists.txt
Normal file
8
native/WslProxy/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(wslproxy C)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
|
||||
add_executable(wslproxy wslproxy.c)
|
||||
target_compile_options(wslproxy PRIVATE -Wall -Wextra -pedantic -Werror -Os)
|
||||
target_link_libraries(wslproxy pthread)
|
||||
3
native/WslProxy/Makefile
Normal file
3
native/WslProxy/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
CPPFLAGS = -Wall -Wextra -pedantic -Werror -Os
|
||||
LDLIBS = -pthread -static
|
||||
wslproxy: $(SOURCES)
|
||||
7
native/WslProxy/README.txt
Normal file
7
native/WslProxy/README.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
To avoid connecting from WSL to Windows (such connections may be blocked by firewall) we connect from Windows to WSL instead.
|
||||
This proxy accepts two clients: one for external (eth0) and one for local (loopback). It then passes data between them with two threads.
|
||||
Client disconnection, signal or any byte written to the stdin kills process.
|
||||
|
||||
CMakeLists is here for CLion.
|
||||
|
||||
To build tool use Makefile. We link it statically because WSL may lack glibc. Kernel ABI is backward compatible, so use some old Linux
|
||||
162
native/WslProxy/wslproxy.c
Normal file
162
native/WslProxy/wslproxy.c
Normal file
@@ -0,0 +1,162 @@
|
||||
#include <stdio.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <pthread.h>
|
||||
|
||||
// Output: [linux-ip] [external-port] [internal-port]
|
||||
// Connect to the external from Windows and to the internal from Linux
|
||||
// Sockets are connected from that moment until byte written to the stdin or SIGINT/SIGHUP sent
|
||||
|
||||
#define JB_WSL_INTERFACE "eth0"
|
||||
|
||||
// Bind to eth0 only
|
||||
static in_addr_t jb_get_wsl_public_ip() {
|
||||
struct ifaddrs *ifaddrs_p_base;
|
||||
if (getifaddrs(&ifaddrs_p_base) != 0) {
|
||||
perror("getifaddrs failed");
|
||||
exit(-1);
|
||||
}
|
||||
for (struct ifaddrs *ifaddrs_p = ifaddrs_p_base; ifaddrs_p != NULL; ifaddrs_p = ifaddrs_p->ifa_next) {
|
||||
// Search for inteface and ipv4
|
||||
if ((ifaddrs_p->ifa_addr->sa_family != AF_INET) ||
|
||||
((strcmp(ifaddrs_p->ifa_name, JB_WSL_INTERFACE) != 0))) {
|
||||
continue;
|
||||
}
|
||||
const struct sockaddr_in *in_addr = (struct sockaddr_in *) ifaddrs_p->ifa_addr;
|
||||
const in_addr_t result = in_addr->sin_addr.s_addr;
|
||||
freeifaddrs(ifaddrs_p_base);
|
||||
return result;
|
||||
}
|
||||
freeifaddrs(ifaddrs_p_base);
|
||||
fprintf(stderr, "No interface %s found", JB_WSL_INTERFACE);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Open internal or external sock, print addr if print_addr
|
||||
static int jb_open_socket(const in_addr_t listen_to, const bool print_addr) {
|
||||
const int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
perror("can't open socket");
|
||||
exit(-1);
|
||||
}
|
||||
struct sockaddr_in addr_p = {0};
|
||||
addr_p.sin_family = AF_INET;
|
||||
addr_p.sin_addr.s_addr = listen_to;
|
||||
if (bind(sock, (struct sockaddr *) &addr_p, sizeof(struct sockaddr_in)) != 0) {
|
||||
perror("can't bind to port");
|
||||
exit(-1);
|
||||
}
|
||||
if (listen(sock, 1) != 0) {
|
||||
perror("socket can't be listen");
|
||||
exit(-1);
|
||||
}
|
||||
bzero(&addr_p, sizeof(addr_p));
|
||||
socklen_t size = sizeof(addr_p);
|
||||
if (getsockname(sock, (struct sockaddr *) &addr_p, &size) != 0) {
|
||||
perror("getsockname failed");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (print_addr) {
|
||||
printf("%s ", inet_ntoa(addr_p.sin_addr));
|
||||
}
|
||||
printf("%d ", ntohs(addr_p.sin_port));
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
struct jb_socket_info {
|
||||
int server_sock_fd; // Listening server socket
|
||||
int client_sock_fd; // Connected (accepted) client
|
||||
};
|
||||
|
||||
// public (external) socket and local (internal)
|
||||
static struct jb_socket_info jb_public = {0}, jb_local = {0};
|
||||
|
||||
// marks socket for the next "select" call if client hasn't been connected yet
|
||||
static void jb_set_select_socket(const struct jb_socket_info *sock, fd_set *sock_set, int *max_sock) {
|
||||
if (sock->client_sock_fd != 0) { // Client already connected
|
||||
return;
|
||||
}
|
||||
FD_SET(sock->server_sock_fd, sock_set); // select socket
|
||||
if (sock->server_sock_fd > *max_sock) {
|
||||
*max_sock = sock->server_sock_fd;
|
||||
}
|
||||
}
|
||||
|
||||
static void jb_set_client_socket(const fd_set *sock_set, struct jb_socket_info *sock) {
|
||||
if (sock->client_sock_fd == 0 && FD_ISSET(sock->server_sock_fd, sock_set)) {
|
||||
if ((sock->client_sock_fd = accept(sock->server_sock_fd, NULL, NULL)) < 0) {
|
||||
perror("accept call failed");
|
||||
exit(-1);
|
||||
}
|
||||
close(sock->server_sock_fd); // Client connected, close listening socket
|
||||
sock->server_sock_fd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Waits for both clients to connect
|
||||
static void jb_connect_accept_clients() {
|
||||
fd_set sock_set;
|
||||
struct timeval time = {.tv_sec = 120, .tv_usec = 0};
|
||||
|
||||
const int stdin_fd = fileno(stdin);
|
||||
while (jb_public.client_sock_fd == 0 || jb_local.client_sock_fd == 0) {
|
||||
FD_ZERO(&sock_set);
|
||||
FD_SET(stdin_fd, &sock_set);
|
||||
int max_sock = stdin_fd;
|
||||
jb_set_select_socket(&jb_local, &sock_set, &max_sock);
|
||||
jb_set_select_socket(&jb_public, &sock_set, &max_sock);
|
||||
if (select(max_sock + 1, &sock_set, NULL, NULL, &time) < 0) {
|
||||
perror("select call failed");
|
||||
exit(-1);
|
||||
}
|
||||
if (FD_ISSET(stdin_fd, &sock_set)) {
|
||||
exit(0);
|
||||
}
|
||||
jb_set_client_socket(&sock_set, &jb_local);
|
||||
jb_set_client_socket(&sock_set, &jb_public);
|
||||
}
|
||||
}
|
||||
|
||||
// Connect source (sock) and destination (another socket)
|
||||
static void *jb_connect(const struct jb_socket_info *sock) {
|
||||
const int source = sock->client_sock_fd;
|
||||
const int dest = (sock == &jb_local ? jb_public : jb_local).client_sock_fd;
|
||||
char buf[4096];
|
||||
size_t bytes;
|
||||
while ((bytes = read(source, buf, sizeof(buf))) > 0) {
|
||||
write(dest, buf, bytes);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void jb_create_thread(struct jb_socket_info *sock) {
|
||||
pthread_t thread;
|
||||
const int result = pthread_create(&thread, NULL, (void *(*)(void *)) &jb_connect, sock);
|
||||
if (result != 0) {
|
||||
fprintf(stderr, "pthread_create failed: %d", result);
|
||||
exit(result);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
jb_public.server_sock_fd = jb_open_socket(jb_get_wsl_public_ip(), true);
|
||||
jb_local.server_sock_fd = jb_open_socket(htonl(INADDR_LOOPBACK), false);
|
||||
|
||||
puts("\n");
|
||||
fflush(stdout);
|
||||
|
||||
jb_connect_accept_clients();
|
||||
|
||||
|
||||
jb_create_thread(&jb_public);
|
||||
jb_create_thread(&jb_local);
|
||||
|
||||
getchar();
|
||||
return 0;
|
||||
}
|
||||
@@ -709,6 +709,7 @@ final class CommunityLibraryLicenses {
|
||||
jetbrainsLibrary("intellij-coverage"),
|
||||
jetbrainsLibrary("intellij-markdown"),
|
||||
jetbrainsLibrary("intellij-test-discovery"),
|
||||
jetbrainsLibrary("io.ktor.network.jvm"),
|
||||
jetbrainsLibrary("jps-build-script-dependencies-bootstrap"),
|
||||
jetbrainsLibrary("jshell-frontend"),
|
||||
jetbrainsLibrary("kotlin-script-runtime"),
|
||||
|
||||
Reference in New Issue
Block a user