feat(http2): Add documentation for using http2 as transport protocol

This commit is contained in:
Σrebe - Romain GERARD 2024-01-23 13:47:59 +01:00
parent 3b4c86bce2
commit f51981ff15
No known key found for this signature in database
GPG key ID: 7A42B4B97E0332F4
2 changed files with 65 additions and 8 deletions

View file

@ -64,8 +64,18 @@ Client:
Usage: wstunnel client [OPTIONS] <ws[s]://wstunnel.server.com[:port]> Usage: wstunnel client [OPTIONS] <ws[s]://wstunnel.server.com[:port]>
Arguments: Arguments:
<ws[s]://wstunnel.server.com[:port]> Address of the wstunnel server <ws[s]|http[s]://wstunnel.server.com[:port]>
Example: With TLS wss://wstunnel.example.com or without ws://wstunnel.example.com Address of the wstunnel server
You can either use websocket or http2 as transport protocol. Use websocket if you are unsure.
Example: For websocket with TLS wss://wstunnel.example.com or without ws://wstunnel.example.com
For http2 with TLS https://wstunnel.example.com or without http://wstunnel.example.com
*WARNING* HTTP2 as transport protocol is harder to make it works because:
- If you are behind a (reverse) proxy/CDN they are going to buffer the whole request before forwarding it to the server
Obviously, this is not going to work for tunneling traffic
- if you have wstunnel behind a reverse proxy, most of them (i.e: nginx) are going to turn http2 request into http1
This is not going to work, because http1 does not support streaming naturally
The only way to make it works with http2 is to have wstunnel directly exposed to the internet without any reverse proxy in front of it
Options: Options:
-L, --local-to-remote <{tcp,udp,socks5,stdio,unix}://[BIND:]PORT:HOST:PORT> -L, --local-to-remote <{tcp,udp,socks5,stdio,unix}://[BIND:]PORT:HOST:PORT>
@ -108,11 +118,21 @@ ws://localhost:8080" my-server`
--tls-verify-certificate --tls-verify-certificate
Enable TLS certificate verification. Enable TLS certificate verification.
Disabled by default. The client will happily connect to any server with self signed certificate. Disabled by default. The client will happily connect to any server with self signed certificate.
-p, --http-proxy <http://USER:PASS@HOST:PORT> -p, --http-proxy <USER:PASS@HOST:PORT>
If set, will use this http proxy to connect to the server If set, will use this http proxy to connect to the server
--http-upgrade-path-prefix <HTTP_UPGRADE_PATH_PREFIX> [env: HTTP_PROXY=]
--http-proxy-login <LOGIN>
If set, will use this login to connect to the http proxy. Override the one from --http-proxy
[env: WSTUNNEL_HTTP_PROXY_LOGIN=]
--http-proxy-password <PASSWORD>
If set, will use this password to connect to the http proxy. Override the one from --http-proxy
[env: WSTUNNEL_HTTP_PROXY_PASSWORD=]
-P, --http-upgrade-path-prefix <HTTP_UPGRADE_PATH_PREFIX>
Use a specific prefix that will show up in the http path during the upgrade request. Use a specific prefix that will show up in the http path during the upgrade request.
Useful if you need to route requests server side but don't have vhosts [default: morille] Useful if you need to route requests server side but don't have vhosts
[env: WSTUNNEL_HTTP_UPGRADE_PATH_PREFIX=]
[default: v1]
--http-upgrade-credentials <USER[:PASS]> --http-upgrade-credentials <USER[:PASS]>
Pass authorization header with basic auth credentials during the upgrade request. Pass authorization header with basic auth credentials during the upgrade request.
If you need more customization, you can use the http_headers option. If you need more customization, you can use the http_headers option.
@ -133,6 +153,7 @@ Usage: wstunnel server [OPTIONS] <ws[s]://0.0.0.0[:port]>
Arguments: Arguments:
<ws[s]://0.0.0.0[:port]> Address of the wstunnel server to bind to <ws[s]://0.0.0.0[:port]> Address of the wstunnel server to bind to
Example: With TLS wss://0.0.0.0:8080 or without ws://[::]:8080 Example: With TLS wss://0.0.0.0:8080 or without ws://[::]:8080
The server is capable of detecting by itself if the request is Websocket or Http2. So you don't need to specify it.
Options: Options:
--socket-so-mark <INT> --socket-so-mark <INT>
@ -192,6 +213,7 @@ docker pull ghcr.io/erebe/wstunnel:latest
* [Proxy easily any traffic with transparent proxy (linux only)](#tproxy) * [Proxy easily any traffic with transparent proxy (linux only)](#tproxy)
* [Reverse tunneling](#reverse) * [Reverse tunneling](#reverse)
* [How to secure access of your wstunnel server](#secure) * [How to secure access of your wstunnel server](#secure)
* [Use HTTP2 instead of websocket for transport protocol](#http2)
* [Maximize your stealthiness/Make your traffic discrete](#stealth) * [Maximize your stealthiness/Make your traffic discrete](#stealth)
### Understand command line syntax <a name="syntax"></a> ### Understand command line syntax <a name="syntax"></a>
@ -384,6 +406,31 @@ Now your wstunnel server, will only accept connection if the client specify the
--- ---
### Use HTTP2 instead of websocket for the transport protocol <a name="http2"></a>
Use this only if websocket is blocked by your firewall/proxy. Otherwise, it is less performant than websocket.
Start your wstunnel server as usual with
```bash
wstunnel server wss://[::]:8080
```
On the client the only difference is to specify https:// instead of wss://
```bash
wstunnel client -L socks5://127.0.0.1:8888 https://myRemoteHost:8080
```
**WARNING** HTTP2 as transport protocol is harder to make it works because:
- If you are behind a (reverse) proxy/CDN they may buffer the whole request before forwarding it to the server.
Cloudflare is doing that, and obviously, this is not going to work for tunneling traffic
- if you have wstunnel behind a reverse proxy, most of them (i.e: nginx) are going to turn http2 request into http1
This is not going to work, because http1 does not support streaming naturally
The only way to make it works with HTTP2 is to have wstunnel server directly exposed to the internet without any reverse proxy in front of it
In addition, you may also want to play with the request headers (i.e: content-length and content-type) to make it looks like normal traffic to bypass your firewall/proxy.
Some firewall may not like to see request with content-length not set, or with content-type set to application/octet-stream
### Maximize your stealthiness/Make your traffic discrete <a name="stealth"></a> ### Maximize your stealthiness/Make your traffic discrete <a name="stealth"></a>
* Use wstunnel with TLS activated (wss://) and use your own certificate * Use wstunnel with TLS activated (wss://) and use your own certificate

View file

@ -46,9 +46,8 @@ use tracing_subscriber::filter::Directive;
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
use url::{Host, Url}; use url::{Host, Url};
/// Use the websockets protocol to tunnel {TCP,UDP} traffic /// Use Websocket or HTTP2 protocol to tunnel {TCP,UDP} traffic
/// wsTunnelClient <---> wsTunnelServer <---> RemoteHost /// wsTunnelClient <---> wsTunnelServer <---> RemoteHost
/// Use secure connection (wss://) to bypass proxies
#[derive(clap::Parser, Debug)] #[derive(clap::Parser, Debug)]
#[command(author, version, about, verbatim_doc_comment, long_about = None)] #[command(author, version, about, verbatim_doc_comment, long_about = None)]
struct Wstunnel { struct Wstunnel {
@ -198,7 +197,16 @@ struct Client {
http_headers: Vec<(HeaderName, HeaderValue)>, http_headers: Vec<(HeaderName, HeaderValue)>,
/// Address of the wstunnel server /// Address of the wstunnel server
/// Example: With TLS wss://wstunnel.example.com or without ws://wstunnel.example.com /// You can either use websocket or http2 as transport protocol. Use websocket if you are unsure.
/// Example: For websocket with TLS wss://wstunnel.example.com or without ws://wstunnel.example.com
/// For http2 with TLS https://wstunnel.example.com or without http://wstunnel.example.com
///
/// *WARNING* HTTP2 as transport protocol is harder to make it works because:
/// - If you are behind a (reverse) proxy/CDN they are going to buffer the whole request before forwarding it to the server
/// Obviously, this is not going to work for tunneling traffic
/// - if you have wstunnel behind a reverse proxy, most of them (i.e: nginx) are going to turn http2 request into http1
/// This is not going to work, because http1 does not support streaming naturally
/// The only way to make it works with http2 is to have wstunnel directly exposed to the internet without any reverse proxy in front of it
#[arg(value_name = "ws[s]|http[s]://wstunnel.server.com[:port]", value_parser = parse_server_url, verbatim_doc_comment)] #[arg(value_name = "ws[s]|http[s]://wstunnel.server.com[:port]", value_parser = parse_server_url, verbatim_doc_comment)]
remote_addr: Url, remote_addr: Url,
} }
@ -207,6 +215,8 @@ struct Client {
struct Server { struct Server {
/// Address of the wstunnel server to bind to /// Address of the wstunnel server to bind to
/// Example: With TLS wss://0.0.0.0:8080 or without ws://[::]:8080 /// Example: With TLS wss://0.0.0.0:8080 or without ws://[::]:8080
///
/// The server is capable of detecting by itself if the request is websocket or http2. So you don't need to specify it.
#[arg(value_name = "ws[s]://0.0.0.0[:port]", value_parser = parse_server_url, verbatim_doc_comment)] #[arg(value_name = "ws[s]://0.0.0.0[:port]", value_parser = parse_server_url, verbatim_doc_comment)]
remote_addr: Url, remote_addr: Url,