forked from cloud/ovgate
OpenVPN client with an authenticated SOCKS5 front door
A userspace VPN gateway: builds an OpenVPN tunnel to a VPNGate node with
the OpenVPN 3 core, terminates it in-process with lwIP, and serves SOCKS5
(RFC 1928/1929, CONNECT and UDP ASSOCIATE) over it. No root, no tun
device, no routing table changes.
Layout follows the module boundaries in docs/ARCHITECTURE.md:
vpngate/ directory fetch + CSV parse (lines run to ~13.5 KB, so the
parser streams rather than splitting on newlines)
selector/ two-phase pick: cheap prior over the whole list, then real
TCP handshake timing of the top K
ovpn/ openvpn3 driven through TunBuilder, packets over a socketpair
netstack/ lwIP: the TCP/IP stack that makes "no root" possible
egress/ the swappable way out, and make-before-break switching
socks5/ the front door
health/ per-window scoring, and the decision to move
app/ wiring, admin HTTP, signals
docs/FEASIBILITY.md is the analysis this was built from, including the
one requirement that is not physically possible -- carrying established
TCP connections across a node switch -- and what is done instead
(zero-progress redial, UDP re-homing, grace-period drain).
Tests: 155 without the tunnel egress, 172 with it. The seam is the egress
factory; selection, scoring, history and probing all run for real.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
// A small async HTTP/1.1 GET client over asio, with TLS support.
|
||||
//
|
||||
// Written rather than pulled in (libcurl) because we need exactly one verb, and
|
||||
// libcurl's threading/blocking model does not fit the single control thread we
|
||||
// run everything else on. Scope is deliberately narrow: GET, redirects, a hard
|
||||
// byte cap, and a deadline.
|
||||
#pragma once
|
||||
|
||||
#include <asio.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
namespace ovg::http {
|
||||
|
||||
struct Url {
|
||||
std::string scheme; // "http" or "https"
|
||||
std::string host;
|
||||
std::string port; // always populated (defaulted from scheme)
|
||||
std::string target; // path + query, starts with '/'
|
||||
};
|
||||
|
||||
bool parse_url(const std::string &text, Url *out);
|
||||
|
||||
struct Response {
|
||||
int status = 0;
|
||||
std::string body;
|
||||
};
|
||||
|
||||
using Handler = std::function<void(std::error_code, Response)>;
|
||||
|
||||
struct Options {
|
||||
std::chrono::milliseconds timeout{30000};
|
||||
size_t max_bytes = 32u * 1024 * 1024;
|
||||
int max_redirects = 3;
|
||||
std::string user_agent = "openvpngate/0.1";
|
||||
// TLS peer verification. Only disable for a mirror you control.
|
||||
bool verify_tls = true;
|
||||
};
|
||||
|
||||
// Invokes `handler` exactly once, on `io`'s executor.
|
||||
void async_get(asio::io_context &io, const std::string &url,
|
||||
const Options &opts, Handler handler);
|
||||
|
||||
} // namespace ovg::http
|
||||
Reference in New Issue
Block a user