From f7e67801a59a13193acc1796140b1487e3e78038 Mon Sep 17 00:00:00 2001 From: Luxferre Date: Sat, 25 Jul 2026 11:14:52 +0300 Subject: [PATCH] init upload --- .gitignore | 3 + Makefile | 23 ++++++ README.md | 108 +++++++++++++++++++++++++++ client/gs-warp-simple.sh | 23 ++++++ server/Dockerfile | 26 +++++++ server/compose.yaml | 22 ++++++ server/entrypoint.sh | 155 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 360 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100755 client/gs-warp-simple.sh create mode 100644 server/Dockerfile create mode 100644 server/compose.yaml create mode 100644 server/entrypoint.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0413138 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.env +client.ovpn +.DS_Store diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5de91c7 --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ +all: + @echo "Usage: make server | make stop-server | make server-secret | make simple" + +server: + @cd server && docker compose up --build -d + +stop-server: + @cd server && docker compose down + +clean: + @cd server && docker compose down -v + +server-secret: + @cd server && printf 'Enter server secret: ' && read -r GS_SECRET && echo "GS_SECRET=$$GS_SECRET" > .env + +ovpn: + @docker cp gsocket-vpn:/vpn/client.ovpn . && echo 'client.ovpn saved!' + +start: + @cd client && sh gs-warp-simple.sh + +stop: + @sudo kill `cat /tmp/gswarp-ov.pid` `cat /tmp/gswarp-gs.pid` && sudo rm -f /tmp/gswarp-*.pid diff --git a/README.md b/README.md new file mode 100644 index 0000000..52f93d0 --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ +# GS-Warp: A turnkey GSocket-tunneled VPN + +## About + +GS-Warp is a simple and straightforward implementation of the idea of tunneling [OpenVPN](https://openvpn.net/) traffic via [Global Socket](https://www.gsocket.io/) Relay Network (GSRN). This setup is especially suitable for installing the server side on a small VPS (Virtual Private Server) and allows you to: + +- prevent potential eavesdroppers on your VPS traffic from knowing your real peer IP, +- avoid provider-side blocking of your VPS, +- staying protected in case of an (unlikely) event of compromising GSRN or GSocket encryption itself, +- have the outgoing traffic server even behind NAT, as no external IP is required for GS-Warp to work. + +## Dependencies + +Server-side dependencies: + +- full (real) root access to the server, +- Docker (recommended), +- OpenVPN (installed within the container), +- GSocket (installed within the container), +- Make (optional but recommended). + +Client-side dependencies: + +- any OpenVPN client, +- GSocket, +- Make (optional but recommended in case of using the "simple" client). + +## Usage + +### On the server + +Assumes having Docker and Make. From the repo root: + +1. Enter and save the GSocket secret: `make server-secret` +2. Build (if necessary) and start the server: `make server` +3. Export the `client.ovpn` file to the current directory: `make ovpn` +4. Stop the server (without removing the data): `make stop-server` +5. Stop the server and remove all data: `make clean` + +### On the client ("simple" approach, Make-based) + +1. Get the `client.ovpn` file from the server and put it into the `client` directory. +2. Run `make start`, enter your GSocket server secret and then your sudo password (if necessary). +3. To stop the client, run `make stop.` + +### On the client (manual approach, POSIX) + +1. Get the `client.ovpn` file from the server. +2. Run these commands directly: `gs-netcat -D -s your_gsocket_secret -p 1194 && sudo openvpn --daemon gs-warp --config client.ovpn` +3. To stop, first stop the OpenVPN process and then gs-netcat. + +### On the client (manual approach, non-POSIX) + +This is suitable for non-POSIX environments. You'll need any OpenVPN client and `gs-netcat` binary for your platform. + +1. Get the `client.ovpn` file from the server and put it into your OpenVPN client's profile. Do not start the client yet. +2. In a separate terminal window, run `gs-netcat -D -s your_gsocket_secret -p 1194`. +3. Start the OpenVPN connection in the client. +4. To stop, first stop the OpenVPN connection and then terminate the gs-netcat process. + +More client options coming soon! + +## FAQ + +### What is the advantage of GS-Warp over a plain VPN on a VPS? + +Potential eavesdroppers, including your own ISP, know that you're connecting to your VPS and can block/throttle this connection at will. Tunneling over GSRN hides the very fact of this connection, as well as provides an additional end-to-end encryption layer. + +Additionally, a plain VPS requires an external IP for you to be able to connect directly. With GSRN, **both peers can be behind NAT** and this won't affect their connectivity in any way. + +### What is the advantage of GS-Warp over plain GSRN tunneling with `gs-netcat`? + +If you only need to have TCP connections tunneled, GS-Warp is an overkill indeed, and you can get away with setting up a SOCKS proxy like this (which even works within containers without special privileges): +``` +# on the server side: +gs-netcat -DlS -s [your_secret] + +# on the client side: +gs-netcat -D -p [your_socks_port] -s [your_secret] +``` + +However, if you also need UDP or other IP traffic forwarded through your tunnel, you need to encapsulate it with a full VPN piped through the TCP channel established via `gs-netcat`. GS-Warp was created to facilitate just that. + +### Can we use the GS-Warp server setup within existing containers? + +Only if you have full root control over the host environment. Namely, you'll need to add `NET_ADMIN` and `NET_RAW` capabilities, `/dev/net/tun` device forwarding and `net.ipv4.ip_forward=1` sysctl setting. + +### Why does GS-Warp use OpenVPN and not e.g. WireGuard or other modern alternatives? + +Since all the end-to-end encryption and traffic masking heavy lifting is done by GSocket anyway, the choice of VPN package for IP traffic encapsulation became merely a matter of convenience. OpenVPN was selected because it has uniform configuration format across all platforms it's officially implemented on (desktop, embedded and mobile), which gives us the broadest compatibility range. + +### I have e.g. an iPad where I can run OpenVPN but cannot run gs-netcat, what do I do? + +Just decouple the client setup. Run gs-netcat on another device on your LAN (or even WAN) and then edit the IP in the `remote 127.0.0.1 1194` line of your `client.ovpn` config file to reflect the address of that device. + +As a bonus, the traffic between your iPad and the node you run `gs-netcat` on will still be protected with OpenVPN encryption. + +### What about Android? + +On Android (at least on ARM64), you can freely run gs-netcat within Termux and then use the official OpenVPN Connect application to connect through it using the very same `client.ovpn` file. Just follow the guide above to run the correct gs-netcat command. Besides this, a dedicated Android helper application is being planned to make running a GSocket-based tunnel much easier for the average user. + +**N.B.:** when running via Termux, don't forget to acquire the wakelock in the notification drawer for the OS to not suddenly suspend the gs-netcat process when idle. + +## Credits + +Created by Luxferre in 2026, released into the public domain with no warranties. + +Thanks to Global Socket and OpenVPN projects for making this possible. diff --git a/client/gs-warp-simple.sh b/client/gs-warp-simple.sh new file mode 100755 index 0000000..ee8339f --- /dev/null +++ b/client/gs-warp-simple.sh @@ -0,0 +1,23 @@ +#!/bin/sh +[ -z "$GS_SECRET" ] && GS_SECRET="$1" +[ -z "$GS_SECRET" ] && printf 'Enter GSocket secret: ' && read -r GS_SECRET +[ -z "$OVPNCFG" ] && OVPNCFG="$2" +[ -z "$OVPNCFG" ] && OVPNCFG="client.ovpn" + +GSPIDFILE='/tmp/gswarp-gs.pid' +OVPIDFILE='/tmp/gswarp-ov.pid' + +BEFORE_PIDS=$(pgrep -x gs-netcat 2>/dev/null) +gs-netcat -D -s "$GS_SECRET" -p 1194 +sleep 0.5 +AFTER_PIDS=$(pgrep -x gs-netcat 2>/dev/null) + +if [ -n "$BEFORE_PIDS" ]; then + echo "$AFTER_PIDS" | grep -v -F -x "$BEFORE_PIDS" > "$GSPIDFILE" +else + echo "$AFTER_PIDS" > "$GSPIDFILE" +fi + +sudo openvpn --daemon gs-warp --config "$OVPNCFG" --writepid "$OVPIDFILE" + +echo 'GS-Warp started' diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000..df97961 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,26 @@ +FROM debian:trixie-slim + +ENV DEBIAN_FRONTEND=noninteractive + +# Install OpenVPN, OpenSSL, IPTables, GSocket and networking utilities +RUN apt-get update && apt-get install -y --no-install-recommends \ + openvpn \ + openssl \ + iptables \ + iproute2 \ + curl \ + ca-certificates \ + procps \ + gsocket \ + && rm -rf /var/lib/apt/lists/* + +# FIX: Switch default iptables engine to legacy mode to bypass container nf_tables restriction +RUN update-alternatives --set iptables /usr/sbin/iptables-legacy && \ + update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy + +WORKDIR /vpn + +COPY entrypoint.sh /vpn/entrypoint.sh +RUN chmod +x /vpn/entrypoint.sh + +ENTRYPOINT ["/vpn/entrypoint.sh"] diff --git a/server/compose.yaml b/server/compose.yaml new file mode 100644 index 0000000..cc9c82c --- /dev/null +++ b/server/compose.yaml @@ -0,0 +1,22 @@ +services: + gsocket-vpn: + build: . + container_name: gsocket-vpn + restart: unless-stopped + environment: + - GS_SECRET=${GS_SECRET} + dns: + - 1.1.1.1 + - 8.8.8.8 + cap_add: + - NET_ADMIN + - NET_RAW + devices: + - /dev/net/tun:/dev/net/tun + sysctls: + - net.ipv4.ip_forward=1 + volumes: + - vpn-data:/vpn + +volumes: + vpn-data: diff --git a/server/entrypoint.sh b/server/entrypoint.sh new file mode 100644 index 0000000..5d161b8 --- /dev/null +++ b/server/entrypoint.sh @@ -0,0 +1,155 @@ +#!/usr/bin/env bash +set -e + +if [ -z "$GS_SECRET" ]; then + echo "[!] ERROR: GS_SECRET environment variable is missing." + echo " Please start the container with -e GS_SECRET=\"your_secret_key\"" + exit 1 +fi + +# Ensure TUN device node exists in container namespace +if [ ! -c /dev/net/tun ]; then + mkdir -p /dev/net + mknod /dev/net/tun c 10 200 + chmod 600 /dev/net/tun +fi + +# Force public DNS resolvers inside container for GSocket relay lookup +echo "nameserver 1.1.1.1" > /etc/resolv.conf +echo "nameserver 8.8.8.8" >> /etc/resolv.conf + +# 1. Generate Certificates & OpenVPN Configs (OpenSSL 3.x compliant) +if [ ! -f /vpn/server.conf ]; then + echo "[+] Generating OpenSSL 3.x compliant SSL/TLS Certificates..." + + # A. Generate CA + openssl req -x509 -newkey rsa:2048 -nodes \ + -keyout /vpn/ca.key -out /vpn/ca.crt -days 3650 \ + -subj "/CN=GSocket-CA" \ + -addext "basicConstraints=critical,CA:TRUE" \ + -addext "keyUsage=critical,keyCertSign,cRLSign" >/dev/null 2>&1 + + # B. Generate Server Cert + cat < /vpn/server_ext.cnf +basicConstraints = CA:FALSE +keyUsage = digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth +subjectAltName = DNS:gsocket, IP:127.0.0.1 +EOF + + openssl req -newkey rsa:2048 -nodes -keyout /vpn/server.key -out /vpn/server.csr -subj "/CN=GSocket-Server" >/dev/null 2>&1 + openssl x509 -req -in /vpn/server.csr -CA /vpn/ca.crt -CAkey /vpn/ca.key -CAcreateserial \ + -out /vpn/server.crt -days 3650 -extfile /vpn/server_ext.cnf >/dev/null 2>&1 + + # C. Generate Client Cert + cat < /vpn/client_ext.cnf +basicConstraints = CA:FALSE +keyUsage = digitalSignature +extendedKeyUsage = clientAuth +EOF + + openssl req -newkey rsa:2048 -nodes -keyout /vpn/client.key -out /vpn/client.csr -subj "/CN=GSocket-Client" >/dev/null 2>&1 + openssl x509 -req -in /vpn/client.csr -CA /vpn/ca.crt -CAkey /vpn/ca.key -CAcreateserial \ + -out /vpn/client.crt -days 3650 -extfile /vpn/client_ext.cnf >/dev/null 2>&1 + + # D. Generate TLS-Crypt Key + openvpn --genkey secret /vpn/tls-crypt.key + + # E. OpenVPN Server Config (uses 'topology subnet' & 'redirect-gateway local') + cat < /vpn/server.conf +dev tun +topology subnet +ca /vpn/ca.crt +cert /vpn/server.crt +key /vpn/server.key +dh none +ecdh-curve prime256v1 +tls-crypt /vpn/tls-crypt.key +server 10.8.0.0 255.255.255.0 +push "redirect-gateway def1 local bypass-dhcp" +push "dhcp-option DNS 1.1.1.1" +push "dhcp-option DNS 8.8.8.8" +keepalive 10 60 +cipher AES-256-GCM +data-ciphers AES-256-GCM:AES-128-GCM +persist-key +persist-tun +tun-mtu 1300 +mssfix 1200 +EOF + + # F. Unified Client Config (Embedded relay routes via net_gateway) + cat < /vpn/client.ovpn +client +dev tun +proto tcp-client +remote 127.0.0.1 1194 +resolv-retry infinite +nobind +persist-key +persist-tun +remote-cert-tls server +cipher AES-256-GCM +tun-mtu 1300 +mssfix 1200 + +# Native OpenVPN routes to bypass GSocket relay nodes via physical default gateway +route j.gs.thc.org 255.255.255.255 net_gateway +route a.gs.thc.org 255.255.255.255 net_gateway +route b.gs.thc.org 255.255.255.255 net_gateway +route c.gs.thc.org 255.255.255.255 net_gateway +route g.gs.thc.org 255.255.255.255 net_gateway + + +$(cat /vpn/ca.crt) + + +$(cat /vpn/client.crt) + + +$(cat /vpn/client.key) + + +$(cat /vpn/tls-crypt.key) + +EOF + + echo "[+] Client config generated at /vpn/client.ovpn" +fi + +# 2. Configure Networking & IPTables inside Container +WAN_IF=$(ip route show default | awk '/default/ {print $5}' | head -n1) +echo "[+] Container WAN Interface detected: $WAN_IF" + +if [ "$(cat /proc/sys/net/ipv4/ip_forward 2>/dev/null)" = "1" ]; then + echo "[+] IPv4 forwarding is active." +else + echo "[!] WARNING: IPv4 forwarding is not active in this container!" +fi + +echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter 2>/dev/null || true +echo 0 > /proc/sys/net/ipv4/conf/default/rp_filter 2>/dev/null || true + +iptables -F +iptables -t nat -F + +iptables -A INPUT -i tun+ -j ACCEPT +iptables -A OUTPUT -o tun+ -j ACCEPT +iptables -A FORWARD -i tun+ -j ACCEPT +iptables -A FORWARD -o tun+ -j ACCEPT + +iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j MASQUERADE +iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1200 + +# 3. Start OpenVPN daemon +echo "[+] Starting local OpenVPN daemon on 127.0.0.1:1194..." +openvpn --config /vpn/server.conf \ + --proto tcp4-server \ + --local 127.0.0.1 \ + --lport 1194 & + +sleep 2 + +# 4. Forward GSocket stream directly to 127.0.0.1:1194 +echo "[+] Starting gs-netcat port forwarder..." +exec gs-netcat -s "$GS_SECRET" -l -d 127.0.0.1 -p 1194