Add full WebTransport support
This commit is contained in:
parent
3bdb461142
commit
42aed6cbb2
38
Cargo.lock
generated
38
Cargo.lock
generated
@ -1920,6 +1920,43 @@ version = "0.25.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
|
checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webtransport-generic"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "git+https://github.com/kixelated/webtransport-rs?rev=ba1a372a7a89e4ba9f9bc027733f82f87aa9a4fd#ba1a372a7a89e4ba9f9bc027733f82f87aa9a4fd"
|
||||||
|
dependencies = [
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webtransport-proto"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "git+https://github.com/kixelated/webtransport-rs?rev=ba1a372a7a89e4ba9f9bc027733f82f87aa9a4fd#ba1a372a7a89e4ba9f9bc027733f82f87aa9a4fd"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"http",
|
||||||
|
"thiserror",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webtransport-quinn"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "git+https://github.com/kixelated/webtransport-rs?rev=ba1a372a7a89e4ba9f9bc027733f82f87aa9a4fd#ba1a372a7a89e4ba9f9bc027733f82f87aa9a4fd"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures",
|
||||||
|
"http",
|
||||||
|
"log",
|
||||||
|
"quinn",
|
||||||
|
"quinn-proto",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"url",
|
||||||
|
"webtransport-generic",
|
||||||
|
"webtransport-proto",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "widestring"
|
name = "widestring"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@ -2088,4 +2125,5 @@ dependencies = [
|
|||||||
"toml",
|
"toml",
|
||||||
"trust-dns-resolver",
|
"trust-dns-resolver",
|
||||||
"webpki-roots",
|
"webpki-roots",
|
||||||
|
"webtransport-quinn",
|
||||||
]
|
]
|
||||||
|
11
Cargo.toml
11
Cargo.toml
@ -68,11 +68,14 @@ rustls-pemfile = { version = "1.0", optional = true }
|
|||||||
tokio-tungstenite = { version = "0.19", optional = true, default-features = false, features = ["handshake"] }
|
tokio-tungstenite = { version = "0.19", optional = true, default-features = false, features = ["handshake"] }
|
||||||
futures-util = { version = "0.3", default-features = false, features = ["async-await", "sink", "std"], optional = true }
|
futures-util = { version = "0.3", default-features = false, features = ["async-await", "sink", "std"], optional = true }
|
||||||
|
|
||||||
|
# webtransport deps
|
||||||
|
webtransport-quinn = { version = "0.6", optional = true }
|
||||||
|
|
||||||
# systemd dep
|
# systemd dep
|
||||||
nix = { version = "0.26", optional = true, default-features = false, features = ["socket"]}
|
nix = { version = "0.26", optional = true, default-features = false, features = ["socket"]}
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["c2s-incoming", "c2s-outgoing", "s2s-incoming", "s2s-outgoing", "tls", "quic", "websocket", "logging", "tls-ca-roots-native", "systemd"]
|
default = ["c2s-incoming", "c2s-outgoing", "s2s-incoming", "s2s-outgoing", "tls", "quic", "websocket", "webtransport", "logging", "tls-ca-roots-native", "systemd"]
|
||||||
|
|
||||||
# you must pick one of these or the other, not both: todo: enable picking both and choosing at runtime
|
# you must pick one of these or the other, not both: todo: enable picking both and choosing at runtime
|
||||||
# don't need either of these if only doing c2s-incoming
|
# don't need either of these if only doing c2s-incoming
|
||||||
@ -97,6 +100,7 @@ s2s-outgoing = ["outgoing", "s2s"]
|
|||||||
tls = ["tokio-rustls", "webpki", "rustls"]
|
tls = ["tokio-rustls", "webpki", "rustls"]
|
||||||
quic = ["quinn", "rustls"]
|
quic = ["quinn", "rustls"]
|
||||||
websocket = ["tokio-tungstenite", "futures-util", "tls"] # websocket+incoming also enables incoming TLS support as it's free
|
websocket = ["tokio-tungstenite", "futures-util", "tls"] # websocket+incoming also enables incoming TLS support as it's free
|
||||||
|
webtransport = ["webtransport-quinn", "quic"] # webtransport requires quic
|
||||||
|
|
||||||
logging = ["rand", "env_logger"]
|
logging = ["rand", "env_logger"]
|
||||||
systemd = ["nix"]
|
systemd = ["nix"]
|
||||||
@ -106,3 +110,8 @@ net-test = []
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
|
||||||
|
# need this until a release is made with this commit in it
|
||||||
|
[patch.crates-io]
|
||||||
|
webtransport-quinn = { git = "https://github.com/kixelated/webtransport-rs", rev = "ba1a372a7a89e4ba9f9bc027733f82f87aa9a4fd" }
|
||||||
|
|
||||||
|
20
README.md
20
README.md
@ -11,11 +11,11 @@
|
|||||||
[![Build Status](https://ci.moparisthe.best/job/moparisthebest/job/xmpp-proxy/job/master/badge/icon%3Fstyle=plastic)](https://ci.moparisthe.best/job/moparisthebest/job/xmpp-proxy/job/master/)
|
[![Build Status](https://ci.moparisthe.best/job/moparisthebest/job/xmpp-proxy/job/master/badge/icon%3Fstyle=plastic)](https://ci.moparisthe.best/job/moparisthebest/job/xmpp-proxy/job/master/)
|
||||||
|
|
||||||
xmpp-proxy is a reverse proxy and outgoing proxy for XMPP servers and clients, providing [STARTTLS], [Direct TLS], [QUIC],
|
xmpp-proxy is a reverse proxy and outgoing proxy for XMPP servers and clients, providing [STARTTLS], [Direct TLS], [QUIC],
|
||||||
[WebSocket C2S], and [WebSocket S2S] connectivity to plain-text XMPP servers and clients and limiting stanza sizes without an XML parser.
|
[WebSocket C2S], [WebSocket S2S], and [WebTransport] connectivity to plain-text XMPP servers and clients and limiting stanza sizes without an XML parser.
|
||||||
|
|
||||||
xmpp-proxy in reverse proxy (incoming) mode will:
|
xmpp-proxy in reverse proxy (incoming) mode will:
|
||||||
1. listen on any number of interfaces/ports
|
1. listen on any number of interfaces/ports
|
||||||
2. accept any STARTTLS, Direct TLS, QUIC, or WebSocket c2s or s2s connections from the internet
|
2. accept any STARTTLS, Direct TLS, QUIC, WebSocket, or WebTransport c2s or s2s connections from the internet
|
||||||
3. terminate TLS
|
3. terminate TLS
|
||||||
4. for s2s require a client cert and validate it correctly (using CAs, host-meta, host-meta2, and POSH) for SASL EXTERNAL auth
|
4. for s2s require a client cert and validate it correctly (using CAs, host-meta, host-meta2, and POSH) for SASL EXTERNAL auth
|
||||||
5. connect them to a local real XMPP server over plain-text TCP
|
5. connect them to a local real XMPP server over plain-text TCP
|
||||||
@ -25,8 +25,8 @@ xmpp-proxy in reverse proxy (incoming) mode will:
|
|||||||
xmpp-proxy in outgoing mode will:
|
xmpp-proxy in outgoing mode will:
|
||||||
1. listen on any number of interfaces/ports
|
1. listen on any number of interfaces/ports
|
||||||
2. accept any plain-text TCP or WebSocket connection from a local XMPP server or client
|
2. accept any plain-text TCP or WebSocket connection from a local XMPP server or client
|
||||||
3. look up the required SRV, [host-meta], host-meta2, and [POSH] records
|
3. look up the required SRV, [host-meta], [host-meta2], and [POSH] records
|
||||||
4. connect to a real XMPP server across the internet over STARTTLS, Direct TLS, QUIC, or WebSocket
|
4. connect to a real XMPP server across the internet over STARTTLS, Direct TLS, QUIC, WebSocket, or WebTransport
|
||||||
5. fallback to next SRV target or defaults as required to fully connect
|
5. fallback to next SRV target or defaults as required to fully connect
|
||||||
6. perform all the proper required certificate validation logic
|
6. perform all the proper required certificate validation logic
|
||||||
7. limit incoming stanza sizes as configured
|
7. limit incoming stanza sizes as configured
|
||||||
@ -137,10 +137,11 @@ choose between 1-4 directions:
|
|||||||
3. `s2s-incoming` - enables a server to accept incoming s2s connections
|
3. `s2s-incoming` - enables a server to accept incoming s2s connections
|
||||||
4. `s2s-outgoing` - enables a server to make outgoing s2s connections
|
4. `s2s-outgoing` - enables a server to make outgoing s2s connections
|
||||||
|
|
||||||
choose between 1-3 transport protocols:
|
choose between 1-4 transport protocols:
|
||||||
1. `tls` - enables STARTTLS/TLS support
|
1. `tls` - enables STARTTLS/TLS support
|
||||||
2. `quic` - enables QUIC support
|
2. `quic` - enables QUIC support
|
||||||
3. `websocket` - enables WebSocket support, also enables TLS incoming support if the appropriate directions are enabled
|
3. `websocket` - enables WebSocket support, also enables TLS incoming support if the appropriate directions are enabled
|
||||||
|
4. `webtransport` - enables WebTransport support, also enables QUIC
|
||||||
|
|
||||||
choose exactly 1 of these methods to get trusted CA roots, not needed if only `c2s-incoming` is enabled:
|
choose exactly 1 of these methods to get trusted CA roots, not needed if only `c2s-incoming` is enabled:
|
||||||
1. `tls-ca-roots-native` - reads CA roots from operating system
|
1. `tls-ca-roots-native` - reads CA roots from operating system
|
||||||
@ -168,15 +169,18 @@ GNU/AGPLv3 - Check LICENSE.md for details
|
|||||||
Thanks [rxml](https://github.com/horazont/rxml) for afl-fuzz seeds
|
Thanks [rxml](https://github.com/horazont/rxml) for afl-fuzz seeds
|
||||||
|
|
||||||
#### Todo
|
#### Todo
|
||||||
1. write "host-meta2" XEP for QUIC and WebSocket S2S Discovery
|
1. seamless Tor integration, connecting to and from .onion domains
|
||||||
2. optional [systemd](https://www.freedesktop.org/software/systemd/man/sd_listen_fds.html) [integration](https://mgdm.net/weblog/systemd/)
|
2. Write WebTransport XEP
|
||||||
3. seamless Tor integration, connecting to and from .onion domains
|
3. Document systemd activation support
|
||||||
|
4. Document use-as-a-library support
|
||||||
|
|
||||||
[STARTTLS]: https://datatracker.ietf.org/doc/html/rfc6120#section-5
|
[STARTTLS]: https://datatracker.ietf.org/doc/html/rfc6120#section-5
|
||||||
[Direct TLS]: https://xmpp.org/extensions/xep-0368.html
|
[Direct TLS]: https://xmpp.org/extensions/xep-0368.html
|
||||||
[QUIC]: https://xmpp.org/extensions/xep-0467.html
|
[QUIC]: https://xmpp.org/extensions/xep-0467.html
|
||||||
[WebSocket C2S]: https://datatracker.ietf.org/doc/html/rfc7395
|
[WebSocket C2S]: https://datatracker.ietf.org/doc/html/rfc7395
|
||||||
[WebSocket S2S]: https://xmpp.org/extensions/xep-0468.html
|
[WebSocket S2S]: https://xmpp.org/extensions/xep-0468.html
|
||||||
|
[WebTransport]: https://www.w3.org/TR/webtransport/
|
||||||
[POSH]: https://datatracker.ietf.org/doc/html/rfc7711
|
[POSH]: https://datatracker.ietf.org/doc/html/rfc7711
|
||||||
[host-meta]: https://xmpp.org/extensions/xep-0156.html
|
[host-meta]: https://xmpp.org/extensions/xep-0156.html
|
||||||
|
[host-meta2]: https://xmpp.org/extensions/inbox/host-meta-2.html
|
||||||
[PROXY protocol]: https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
|
[PROXY protocol]: https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
|
||||||
|
@ -47,7 +47,7 @@ perms_optional() {
|
|||||||
all_features() {
|
all_features() {
|
||||||
for optional in "" $(perms_optional logging systemd)
|
for optional in "" $(perms_optional logging systemd)
|
||||||
do
|
do
|
||||||
for proto in $(perms tls quic websocket)
|
for proto in $(perms tls quic websocket webtransport)
|
||||||
do
|
do
|
||||||
for direction in $(perms c2s-incoming c2s-outgoing s2s-incoming s2s-outgoing)
|
for direction in $(perms c2s-incoming c2s-outgoing s2s-incoming s2s-outgoing)
|
||||||
do
|
do
|
||||||
@ -61,7 +61,7 @@ all_features() {
|
|||||||
|
|
||||||
for optional in "" $(perms_optional logging systemd)
|
for optional in "" $(perms_optional logging systemd)
|
||||||
do
|
do
|
||||||
for proto in $(perms tls quic websocket)
|
for proto in $(perms tls quic websocket webtransport)
|
||||||
do
|
do
|
||||||
echo c2s-incoming,$proto$optional
|
echo c2s-incoming,$proto$optional
|
||||||
done
|
done
|
||||||
|
23
integration/29-webtransport-host-meta-json/example.org.zone
Normal file
23
integration/29-webtransport-host-meta-json/example.org.zone
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
$TTL 300
|
||||||
|
; example.org
|
||||||
|
@ IN SOA ns1.example.org. postmaster.example.org. (
|
||||||
|
2018111111 ; Serial
|
||||||
|
28800 ; Refresh
|
||||||
|
1800 ; Retry
|
||||||
|
604800 ; Expire - 1 week
|
||||||
|
86400 ) ; Negative Cache TTL
|
||||||
|
IN NS ns1
|
||||||
|
ns1 IN A 192.5.0.10
|
||||||
|
server1 IN A 192.5.0.20
|
||||||
|
server2 IN A 192.5.0.30
|
||||||
|
xp1 IN A 192.5.0.40
|
||||||
|
xp2 IN A 192.5.0.50
|
||||||
|
xp3 IN A 192.5.0.60
|
||||||
|
web1 IN A 192.5.0.70
|
||||||
|
web2 IN A 192.5.0.80
|
||||||
|
|
||||||
|
one IN CNAME web1
|
||||||
|
two IN CNAME web2
|
||||||
|
|
||||||
|
scansion.one IN CNAME xp3
|
||||||
|
scansion.two IN CNAME xp3
|
48
integration/29-webtransport-host-meta-json/nginx1.conf
Normal file
48
integration/29-webtransport-host-meta-json/nginx1.conf
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
daemon off;
|
||||||
|
worker_processes 1;
|
||||||
|
error_log stderr;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
access_log /dev/stdout;
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name one.example.org;
|
||||||
|
|
||||||
|
ssl_certificate /etc/prosody/certs/one.example.org.crt;
|
||||||
|
ssl_certificate_key /etc/prosody/certs/one.example.org.key;
|
||||||
|
|
||||||
|
location = /.well-known/host-meta.json {
|
||||||
|
default_type application/json;
|
||||||
|
return 200 '{
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"rel": "urn:xmpp:alt-connections:s2s-webtransport",
|
||||||
|
"href": "https://xp1.example.org/xmpp-webtransport",
|
||||||
|
"ips": [
|
||||||
|
"192.5.0.40"
|
||||||
|
],
|
||||||
|
"priority": 15,
|
||||||
|
"weight": 50,
|
||||||
|
"sni": "xp1.example.org"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "urn:xmpp:alt-connections:webtransport",
|
||||||
|
"href": "https://xp1.example.org/xmpp-webtransport",
|
||||||
|
"ips": [
|
||||||
|
"192.5.0.40"
|
||||||
|
],
|
||||||
|
"priority": 15,
|
||||||
|
"weight": 50,
|
||||||
|
"sni": "xp1.example.org"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
48
integration/29-webtransport-host-meta-json/nginx2.conf
Normal file
48
integration/29-webtransport-host-meta-json/nginx2.conf
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
daemon off;
|
||||||
|
worker_processes 1;
|
||||||
|
error_log stderr;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
access_log /dev/stdout;
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name two.example.org;
|
||||||
|
|
||||||
|
ssl_certificate /etc/prosody/certs/two.example.org.crt;
|
||||||
|
ssl_certificate_key /etc/prosody/certs/two.example.org.key;
|
||||||
|
|
||||||
|
location = /.well-known/host-meta.json {
|
||||||
|
default_type application/json;
|
||||||
|
return 200 '{
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"rel": "urn:xmpp:alt-connections:s2s-webtransport",
|
||||||
|
"href": "https://xp2.example.org/xmpp-webtransport",
|
||||||
|
"ips": [
|
||||||
|
"192.5.0.50"
|
||||||
|
],
|
||||||
|
"priority": 15,
|
||||||
|
"weight": 50,
|
||||||
|
"sni": "xp2.example.org"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "urn:xmpp:alt-connections:webtransport",
|
||||||
|
"href": "https://xp2.example.org/xmpp-webtransport",
|
||||||
|
"ips": [
|
||||||
|
"192.5.0.50"
|
||||||
|
],
|
||||||
|
"priority": 15,
|
||||||
|
"weight": 50,
|
||||||
|
"sni": "xp2.example.org"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
251
integration/29-webtransport-host-meta-json/prosody1.cfg.lua
Normal file
251
integration/29-webtransport-host-meta-json/prosody1.cfg.lua
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
--Important for systemd
|
||||||
|
-- daemonize is important for systemd. if you set this to false the systemd startup will freeze.
|
||||||
|
daemonize = false
|
||||||
|
run_as_root = true
|
||||||
|
|
||||||
|
pidfile = "/run/prosody/prosody.pid"
|
||||||
|
|
||||||
|
plugin_paths = { "/opt/xmpp-proxy/prosody-modules", "/opt/prosody-modules" }
|
||||||
|
|
||||||
|
-- Prosody Example Configuration File
|
||||||
|
--
|
||||||
|
-- Information on configuring Prosody can be found on our
|
||||||
|
-- website at https://prosody.im/doc/configure
|
||||||
|
--
|
||||||
|
-- Tip: You can check that the syntax of this file is correct
|
||||||
|
-- when you have finished by running this command:
|
||||||
|
-- prosodyctl check config
|
||||||
|
-- If there are any errors, it will let you know what and where
|
||||||
|
-- they are, otherwise it will keep quiet.
|
||||||
|
--
|
||||||
|
-- The only thing left to do is rename this file to remove the .dist ending, and fill in the
|
||||||
|
-- blanks. Good luck, and happy Jabbering!
|
||||||
|
|
||||||
|
|
||||||
|
---------- Server-wide settings ----------
|
||||||
|
-- Settings in this section apply to the whole server and are the default settings
|
||||||
|
-- for any virtual hosts
|
||||||
|
|
||||||
|
-- This is a (by default, empty) list of accounts that are admins
|
||||||
|
-- for the server. Note that you must create the accounts separately
|
||||||
|
-- (see https://prosody.im/doc/creating_accounts for info)
|
||||||
|
-- Example: admins = { "user1@example.com", "user2@example.net" }
|
||||||
|
admins = { }
|
||||||
|
|
||||||
|
-- Enable use of libevent for better performance under high load
|
||||||
|
-- For more information see: https://prosody.im/doc/libevent
|
||||||
|
--use_libevent = true
|
||||||
|
|
||||||
|
-- Prosody will always look in its source directory for modules, but
|
||||||
|
-- this option allows you to specify additional locations where Prosody
|
||||||
|
-- will look for modules first. For community modules, see https://modules.prosody.im/
|
||||||
|
--plugin_paths = {}
|
||||||
|
|
||||||
|
-- This is the list of modules Prosody will load on startup.
|
||||||
|
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
|
||||||
|
-- Documentation for bundled modules can be found at: https://prosody.im/doc/modules
|
||||||
|
modules_enabled = {
|
||||||
|
|
||||||
|
-- Generally required
|
||||||
|
"roster"; -- Allow users to have a roster. Recommended ;)
|
||||||
|
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
|
||||||
|
--"tls"; -- Add support for secure TLS on c2s/s2s connections
|
||||||
|
--"dialback"; -- s2s dialback support
|
||||||
|
"disco"; -- Service discovery
|
||||||
|
|
||||||
|
-- Not essential, but recommended
|
||||||
|
"carbons"; -- Keep multiple clients in sync
|
||||||
|
"pep"; -- Enables users to publish their avatar, mood, activity, playing music and more
|
||||||
|
"private"; -- Private XML storage (for room bookmarks, etc.)
|
||||||
|
"blocklist"; -- Allow users to block communications with other users
|
||||||
|
"vcard4"; -- User profiles (stored in PEP)
|
||||||
|
"vcard_legacy"; -- Conversion between legacy vCard and PEP Avatar, vcard
|
||||||
|
"limits"; -- Enable bandwidth limiting for XMPP connections
|
||||||
|
|
||||||
|
-- Nice to have
|
||||||
|
"version"; -- Replies to server version requests
|
||||||
|
"uptime"; -- Report how long server has been running
|
||||||
|
"time"; -- Let others know the time here on this server
|
||||||
|
"ping"; -- Replies to XMPP pings with pongs
|
||||||
|
"register"; -- Allow users to register on this server using a client and change passwords
|
||||||
|
--"mam"; -- Store messages in an archive and allow users to access it
|
||||||
|
--"csi_simple"; -- Simple Mobile optimizations
|
||||||
|
|
||||||
|
-- Admin interfaces
|
||||||
|
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
|
||||||
|
--"admin_telnet"; -- Opens telnet console interface on localhost port 5582
|
||||||
|
|
||||||
|
-- HTTP modules
|
||||||
|
--"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
|
||||||
|
--"websocket"; -- XMPP over WebSockets
|
||||||
|
--"http_files"; -- Serve static files from a directory over HTTP
|
||||||
|
|
||||||
|
-- Other specific functionality
|
||||||
|
--"groups"; -- Shared roster support
|
||||||
|
--"server_contact_info"; -- Publish contact information for this service
|
||||||
|
--"announce"; -- Send announcement to all online users
|
||||||
|
--"welcome"; -- Welcome users who register accounts
|
||||||
|
--"watchregistrations"; -- Alert admins of registrations
|
||||||
|
--"motd"; -- Send a message to users when they log in
|
||||||
|
--"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
|
||||||
|
--"proxy65"; -- Enables a file transfer proxy service which clients behind NAT can use
|
||||||
|
"net_proxy";
|
||||||
|
"s2s_outgoing_proxy";
|
||||||
|
}
|
||||||
|
|
||||||
|
-- These modules are auto-loaded, but should you want
|
||||||
|
-- to disable them then uncomment them here:
|
||||||
|
modules_disabled = {
|
||||||
|
-- "offline"; -- Store offline messages
|
||||||
|
-- "c2s"; -- Handle client connections
|
||||||
|
-- "s2s"; -- Handle server-to-server connections
|
||||||
|
-- "posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Disable account creation by default, for security
|
||||||
|
-- For more information see https://prosody.im/doc/creating_accounts
|
||||||
|
allow_registration = false
|
||||||
|
|
||||||
|
-- we don't need prosody doing any encryption, xmpp-proxy does this now
|
||||||
|
-- these are likely set to true somewhere in your file, find them, make them false
|
||||||
|
-- you can also remove all certificates from your config
|
||||||
|
s2s_require_encryption = false
|
||||||
|
s2s_secure_auth = false
|
||||||
|
|
||||||
|
-- xmpp-proxy outgoing is listening on this port, make all outgoing s2s connections directly to here
|
||||||
|
s2s_outgoing_proxy = { "192.5.0.40", 15270 }
|
||||||
|
|
||||||
|
-- handle PROXY protocol on these ports
|
||||||
|
proxy_port_mappings = {
|
||||||
|
[15222] = "c2s",
|
||||||
|
[15269] = "s2s"
|
||||||
|
}
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Specifies a list of trusted hosts or networks which may use the PROXY protocol
|
||||||
|
If not specified, it will default to: 127.0.0.1, ::1 (local connections only)
|
||||||
|
An empty table ({}) can be configured to allow connections from any source.
|
||||||
|
Please read the module documentation about potential security impact.
|
||||||
|
]]--
|
||||||
|
proxy_trusted_proxies = {
|
||||||
|
"192.5.0.40"
|
||||||
|
}
|
||||||
|
|
||||||
|
-- don't listen on any normal c2s/s2s ports (xmpp-proxy listens on these now)
|
||||||
|
-- you might need to comment these out further down in your config file if you set them
|
||||||
|
c2s_ports = {}
|
||||||
|
legacy_ssl_ports = {}
|
||||||
|
-- you MUST have at least one s2s_ports defined if you want outgoing S2S to work, don't ask..
|
||||||
|
s2s_ports = {15268}
|
||||||
|
|
||||||
|
-- Force clients to use encrypted connections? This option will
|
||||||
|
-- prevent clients from authenticating unless they are using encryption.
|
||||||
|
|
||||||
|
c2s_require_encryption = false
|
||||||
|
allow_unencrypted_plain_auth = true
|
||||||
|
|
||||||
|
-- Some servers have invalid or self-signed certificates. You can list
|
||||||
|
-- remote domains here that will not be required to authenticate using
|
||||||
|
-- certificates. They will be authenticated using DNS instead, even
|
||||||
|
-- when s2s_secure_auth is enabled.
|
||||||
|
|
||||||
|
--s2s_insecure_domains = { "insecure.example" }
|
||||||
|
|
||||||
|
-- Even if you disable s2s_secure_auth, you can still require valid
|
||||||
|
-- certificates for some domains by specifying a list here.
|
||||||
|
|
||||||
|
--s2s_secure_domains = { "jabber.org" }
|
||||||
|
|
||||||
|
-- Enable rate limits for incoming client and server connections
|
||||||
|
|
||||||
|
limits = {
|
||||||
|
c2s = {
|
||||||
|
rate = "10kb/s";
|
||||||
|
};
|
||||||
|
s2sin = {
|
||||||
|
rate = "30kb/s";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Select the authentication backend to use. The 'internal' providers
|
||||||
|
-- use Prosody's configured data storage to store the authentication data.
|
||||||
|
|
||||||
|
authentication = "internal_hashed"
|
||||||
|
|
||||||
|
-- Select the storage backend to use. By default Prosody uses flat files
|
||||||
|
-- in its configured data directory, but it also supports more backends
|
||||||
|
-- through modules. An "sql" backend is included by default, but requires
|
||||||
|
-- additional dependencies. See https://prosody.im/doc/storage for more info.
|
||||||
|
|
||||||
|
--storage = "sql" -- Default is "internal"
|
||||||
|
|
||||||
|
-- For the "sql" backend, you can uncomment *one* of the below to configure:
|
||||||
|
--sql = { driver = "SQLite3", database = "prosody.sqlite" } -- Default. 'database' is the filename.
|
||||||
|
--sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
|
||||||
|
--sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
|
||||||
|
|
||||||
|
|
||||||
|
-- Archiving configuration
|
||||||
|
-- If mod_mam is enabled, Prosody will store a copy of every message. This
|
||||||
|
-- is used to synchronize conversations between multiple clients, even if
|
||||||
|
-- they are offline. This setting controls how long Prosody will keep
|
||||||
|
-- messages in the archive before removing them.
|
||||||
|
|
||||||
|
archive_expires_after = "1w" -- Remove archived messages after 1 week
|
||||||
|
|
||||||
|
-- You can also configure messages to be stored in-memory only. For more
|
||||||
|
-- archiving options, see https://prosody.im/doc/modules/mod_mam
|
||||||
|
|
||||||
|
-- Logging configuration
|
||||||
|
-- For advanced logging see https://prosody.im/doc/logging
|
||||||
|
log = {
|
||||||
|
-- info = "prosody.log"; -- Change 'info' to 'debug' for verbose logging
|
||||||
|
-- error = "prosody.err";
|
||||||
|
--info = "*syslog"; -- Uncomment this for logging to syslog
|
||||||
|
debug = "*console"; -- Log to the console, useful for debugging with daemonize=false
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Uncomment to enable statistics
|
||||||
|
-- For more info see https://prosody.im/doc/statistics
|
||||||
|
-- statistics = "internal"
|
||||||
|
|
||||||
|
-- Certificates
|
||||||
|
-- Every virtual host and component needs a certificate so that clients and
|
||||||
|
-- servers can securely verify its identity. Prosody will automatically load
|
||||||
|
-- certificates/keys from the directory specified here.
|
||||||
|
-- For more information, including how to use 'prosodyctl' to auto-import certificates
|
||||||
|
-- (from e.g. Let's Encrypt) see https://prosody.im/doc/certificates
|
||||||
|
|
||||||
|
-- Location of directory to find certificates in (relative to main config file):
|
||||||
|
certificates = "certs"
|
||||||
|
|
||||||
|
-- HTTPS currently only supports a single certificate, specify it here:
|
||||||
|
--https_certificate = "/etc/prosody/certs/localhost.crt"
|
||||||
|
|
||||||
|
----------- Virtual hosts -----------
|
||||||
|
-- You need to add a VirtualHost entry for each domain you wish Prosody to serve.
|
||||||
|
-- Settings under each VirtualHost entry apply *only* to that host.
|
||||||
|
|
||||||
|
VirtualHost "one.example.org"
|
||||||
|
|
||||||
|
--VirtualHost "example.com"
|
||||||
|
-- certificate = "/path/to/example.crt"
|
||||||
|
|
||||||
|
------ Components ------
|
||||||
|
-- You can specify components to add hosts that provide special services,
|
||||||
|
-- like multi-user conferences, and transports.
|
||||||
|
-- For more information on components, see https://prosody.im/doc/components
|
||||||
|
|
||||||
|
---Set up a MUC (multi-user chat) room server on conference.example.com:
|
||||||
|
--Component "conference.example.com" "muc"
|
||||||
|
--- Store MUC messages in an archive and allow users to access it
|
||||||
|
--modules_enabled = { "muc_mam" }
|
||||||
|
|
||||||
|
---Set up an external component (default component port is 5347)
|
||||||
|
--
|
||||||
|
-- External components allow adding various services, such as gateways/
|
||||||
|
-- transports to other networks like ICQ, MSN and Yahoo. For more info
|
||||||
|
-- see: https://prosody.im/doc/components#adding_an_external_component
|
||||||
|
--
|
||||||
|
--Component "gateway.example.com"
|
||||||
|
-- component_secret = "password"
|
251
integration/29-webtransport-host-meta-json/prosody2.cfg.lua
Normal file
251
integration/29-webtransport-host-meta-json/prosody2.cfg.lua
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
--Important for systemd
|
||||||
|
-- daemonize is important for systemd. if you set this to false the systemd startup will freeze.
|
||||||
|
daemonize = false
|
||||||
|
run_as_root = true
|
||||||
|
|
||||||
|
pidfile = "/run/prosody/prosody.pid"
|
||||||
|
|
||||||
|
plugin_paths = { "/opt/xmpp-proxy/prosody-modules", "/opt/prosody-modules" }
|
||||||
|
|
||||||
|
-- Prosody Example Configuration File
|
||||||
|
--
|
||||||
|
-- Information on configuring Prosody can be found on our
|
||||||
|
-- website at https://prosody.im/doc/configure
|
||||||
|
--
|
||||||
|
-- Tip: You can check that the syntax of this file is correct
|
||||||
|
-- when you have finished by running this command:
|
||||||
|
-- prosodyctl check config
|
||||||
|
-- If there are any errors, it will let you know what and where
|
||||||
|
-- they are, otherwise it will keep quiet.
|
||||||
|
--
|
||||||
|
-- The only thing left to do is rename this file to remove the .dist ending, and fill in the
|
||||||
|
-- blanks. Good luck, and happy Jabbering!
|
||||||
|
|
||||||
|
|
||||||
|
---------- Server-wide settings ----------
|
||||||
|
-- Settings in this section apply to the whole server and are the default settings
|
||||||
|
-- for any virtual hosts
|
||||||
|
|
||||||
|
-- This is a (by default, empty) list of accounts that are admins
|
||||||
|
-- for the server. Note that you must create the accounts separately
|
||||||
|
-- (see https://prosody.im/doc/creating_accounts for info)
|
||||||
|
-- Example: admins = { "user1@example.com", "user2@example.net" }
|
||||||
|
admins = { }
|
||||||
|
|
||||||
|
-- Enable use of libevent for better performance under high load
|
||||||
|
-- For more information see: https://prosody.im/doc/libevent
|
||||||
|
--use_libevent = true
|
||||||
|
|
||||||
|
-- Prosody will always look in its source directory for modules, but
|
||||||
|
-- this option allows you to specify additional locations where Prosody
|
||||||
|
-- will look for modules first. For community modules, see https://modules.prosody.im/
|
||||||
|
--plugin_paths = {}
|
||||||
|
|
||||||
|
-- This is the list of modules Prosody will load on startup.
|
||||||
|
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
|
||||||
|
-- Documentation for bundled modules can be found at: https://prosody.im/doc/modules
|
||||||
|
modules_enabled = {
|
||||||
|
|
||||||
|
-- Generally required
|
||||||
|
"roster"; -- Allow users to have a roster. Recommended ;)
|
||||||
|
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
|
||||||
|
--"tls"; -- Add support for secure TLS on c2s/s2s connections
|
||||||
|
--"dialback"; -- s2s dialback support
|
||||||
|
"disco"; -- Service discovery
|
||||||
|
|
||||||
|
-- Not essential, but recommended
|
||||||
|
"carbons"; -- Keep multiple clients in sync
|
||||||
|
"pep"; -- Enables users to publish their avatar, mood, activity, playing music and more
|
||||||
|
"private"; -- Private XML storage (for room bookmarks, etc.)
|
||||||
|
"blocklist"; -- Allow users to block communications with other users
|
||||||
|
"vcard4"; -- User profiles (stored in PEP)
|
||||||
|
"vcard_legacy"; -- Conversion between legacy vCard and PEP Avatar, vcard
|
||||||
|
"limits"; -- Enable bandwidth limiting for XMPP connections
|
||||||
|
|
||||||
|
-- Nice to have
|
||||||
|
"version"; -- Replies to server version requests
|
||||||
|
"uptime"; -- Report how long server has been running
|
||||||
|
"time"; -- Let others know the time here on this server
|
||||||
|
"ping"; -- Replies to XMPP pings with pongs
|
||||||
|
"register"; -- Allow users to register on this server using a client and change passwords
|
||||||
|
--"mam"; -- Store messages in an archive and allow users to access it
|
||||||
|
--"csi_simple"; -- Simple Mobile optimizations
|
||||||
|
|
||||||
|
-- Admin interfaces
|
||||||
|
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
|
||||||
|
--"admin_telnet"; -- Opens telnet console interface on localhost port 5582
|
||||||
|
|
||||||
|
-- HTTP modules
|
||||||
|
--"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
|
||||||
|
--"websocket"; -- XMPP over WebSockets
|
||||||
|
--"http_files"; -- Serve static files from a directory over HTTP
|
||||||
|
|
||||||
|
-- Other specific functionality
|
||||||
|
--"groups"; -- Shared roster support
|
||||||
|
--"server_contact_info"; -- Publish contact information for this service
|
||||||
|
--"announce"; -- Send announcement to all online users
|
||||||
|
--"welcome"; -- Welcome users who register accounts
|
||||||
|
--"watchregistrations"; -- Alert admins of registrations
|
||||||
|
--"motd"; -- Send a message to users when they log in
|
||||||
|
--"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
|
||||||
|
--"proxy65"; -- Enables a file transfer proxy service which clients behind NAT can use
|
||||||
|
"net_proxy";
|
||||||
|
"s2s_outgoing_proxy";
|
||||||
|
}
|
||||||
|
|
||||||
|
-- These modules are auto-loaded, but should you want
|
||||||
|
-- to disable them then uncomment them here:
|
||||||
|
modules_disabled = {
|
||||||
|
-- "offline"; -- Store offline messages
|
||||||
|
-- "c2s"; -- Handle client connections
|
||||||
|
-- "s2s"; -- Handle server-to-server connections
|
||||||
|
-- "posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Disable account creation by default, for security
|
||||||
|
-- For more information see https://prosody.im/doc/creating_accounts
|
||||||
|
allow_registration = false
|
||||||
|
|
||||||
|
-- we don't need prosody doing any encryption, xmpp-proxy does this now
|
||||||
|
-- these are likely set to true somewhere in your file, find them, make them false
|
||||||
|
-- you can also remove all certificates from your config
|
||||||
|
s2s_require_encryption = false
|
||||||
|
s2s_secure_auth = false
|
||||||
|
|
||||||
|
-- xmpp-proxy outgoing is listening on this port, make all outgoing s2s connections directly to here
|
||||||
|
s2s_outgoing_proxy = { "192.5.0.50", 15270 }
|
||||||
|
|
||||||
|
-- handle PROXY protocol on these ports
|
||||||
|
proxy_port_mappings = {
|
||||||
|
[15222] = "c2s",
|
||||||
|
[15269] = "s2s"
|
||||||
|
}
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Specifies a list of trusted hosts or networks which may use the PROXY protocol
|
||||||
|
If not specified, it will default to: 127.0.0.1, ::1 (local connections only)
|
||||||
|
An empty table ({}) can be configured to allow connections from any source.
|
||||||
|
Please read the module documentation about potential security impact.
|
||||||
|
]]--
|
||||||
|
proxy_trusted_proxies = {
|
||||||
|
"192.5.0.50"
|
||||||
|
}
|
||||||
|
|
||||||
|
-- don't listen on any normal c2s/s2s ports (xmpp-proxy listens on these now)
|
||||||
|
-- you might need to comment these out further down in your config file if you set them
|
||||||
|
c2s_ports = {}
|
||||||
|
legacy_ssl_ports = {}
|
||||||
|
-- you MUST have at least one s2s_ports defined if you want outgoing S2S to work, don't ask..
|
||||||
|
s2s_ports = {15268}
|
||||||
|
|
||||||
|
-- Force clients to use encrypted connections? This option will
|
||||||
|
-- prevent clients from authenticating unless they are using encryption.
|
||||||
|
|
||||||
|
c2s_require_encryption = false
|
||||||
|
allow_unencrypted_plain_auth = true
|
||||||
|
|
||||||
|
-- Some servers have invalid or self-signed certificates. You can list
|
||||||
|
-- remote domains here that will not be required to authenticate using
|
||||||
|
-- certificates. They will be authenticated using DNS instead, even
|
||||||
|
-- when s2s_secure_auth is enabled.
|
||||||
|
|
||||||
|
--s2s_insecure_domains = { "insecure.example" }
|
||||||
|
|
||||||
|
-- Even if you disable s2s_secure_auth, you can still require valid
|
||||||
|
-- certificates for some domains by specifying a list here.
|
||||||
|
|
||||||
|
--s2s_secure_domains = { "jabber.org" }
|
||||||
|
|
||||||
|
-- Enable rate limits for incoming client and server connections
|
||||||
|
|
||||||
|
limits = {
|
||||||
|
c2s = {
|
||||||
|
rate = "10kb/s";
|
||||||
|
};
|
||||||
|
s2sin = {
|
||||||
|
rate = "30kb/s";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Select the authentication backend to use. The 'internal' providers
|
||||||
|
-- use Prosody's configured data storage to store the authentication data.
|
||||||
|
|
||||||
|
authentication = "internal_hashed"
|
||||||
|
|
||||||
|
-- Select the storage backend to use. By default Prosody uses flat files
|
||||||
|
-- in its configured data directory, but it also supports more backends
|
||||||
|
-- through modules. An "sql" backend is included by default, but requires
|
||||||
|
-- additional dependencies. See https://prosody.im/doc/storage for more info.
|
||||||
|
|
||||||
|
--storage = "sql" -- Default is "internal"
|
||||||
|
|
||||||
|
-- For the "sql" backend, you can uncomment *one* of the below to configure:
|
||||||
|
--sql = { driver = "SQLite3", database = "prosody.sqlite" } -- Default. 'database' is the filename.
|
||||||
|
--sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
|
||||||
|
--sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
|
||||||
|
|
||||||
|
|
||||||
|
-- Archiving configuration
|
||||||
|
-- If mod_mam is enabled, Prosody will store a copy of every message. This
|
||||||
|
-- is used to synchronize conversations between multiple clients, even if
|
||||||
|
-- they are offline. This setting controls how long Prosody will keep
|
||||||
|
-- messages in the archive before removing them.
|
||||||
|
|
||||||
|
archive_expires_after = "1w" -- Remove archived messages after 1 week
|
||||||
|
|
||||||
|
-- You can also configure messages to be stored in-memory only. For more
|
||||||
|
-- archiving options, see https://prosody.im/doc/modules/mod_mam
|
||||||
|
|
||||||
|
-- Logging configuration
|
||||||
|
-- For advanced logging see https://prosody.im/doc/logging
|
||||||
|
log = {
|
||||||
|
-- info = "prosody.log"; -- Change 'info' to 'debug' for verbose logging
|
||||||
|
-- error = "prosody.err";
|
||||||
|
--info = "*syslog"; -- Uncomment this for logging to syslog
|
||||||
|
debug = "*console"; -- Log to the console, useful for debugging with daemonize=false
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Uncomment to enable statistics
|
||||||
|
-- For more info see https://prosody.im/doc/statistics
|
||||||
|
-- statistics = "internal"
|
||||||
|
|
||||||
|
-- Certificates
|
||||||
|
-- Every virtual host and component needs a certificate so that clients and
|
||||||
|
-- servers can securely verify its identity. Prosody will automatically load
|
||||||
|
-- certificates/keys from the directory specified here.
|
||||||
|
-- For more information, including how to use 'prosodyctl' to auto-import certificates
|
||||||
|
-- (from e.g. Let's Encrypt) see https://prosody.im/doc/certificates
|
||||||
|
|
||||||
|
-- Location of directory to find certificates in (relative to main config file):
|
||||||
|
certificates = "certs"
|
||||||
|
|
||||||
|
-- HTTPS currently only supports a single certificate, specify it here:
|
||||||
|
--https_certificate = "/etc/prosody/certs/localhost.crt"
|
||||||
|
|
||||||
|
----------- Virtual hosts -----------
|
||||||
|
-- You need to add a VirtualHost entry for each domain you wish Prosody to serve.
|
||||||
|
-- Settings under each VirtualHost entry apply *only* to that host.
|
||||||
|
|
||||||
|
VirtualHost "two.example.org"
|
||||||
|
|
||||||
|
--VirtualHost "example.com"
|
||||||
|
-- certificate = "/path/to/example.crt"
|
||||||
|
|
||||||
|
------ Components ------
|
||||||
|
-- You can specify components to add hosts that provide special services,
|
||||||
|
-- like multi-user conferences, and transports.
|
||||||
|
-- For more information on components, see https://prosody.im/doc/components
|
||||||
|
|
||||||
|
---Set up a MUC (multi-user chat) room server on conference.example.com:
|
||||||
|
--Component "conference.example.com" "muc"
|
||||||
|
--- Store MUC messages in an archive and allow users to access it
|
||||||
|
--modules_enabled = { "muc_mam" }
|
||||||
|
|
||||||
|
---Set up an external component (default component port is 5347)
|
||||||
|
--
|
||||||
|
-- External components allow adding various services, such as gateways/
|
||||||
|
-- transports to other networks like ICQ, MSN and Yahoo. For more info
|
||||||
|
-- see: https://prosody.im/doc/components#adding_an_external_component
|
||||||
|
--
|
||||||
|
--Component "gateway.example.com"
|
||||||
|
-- component_secret = "password"
|
42
integration/29-webtransport-host-meta-json/xmpp-proxy1.toml
Normal file
42
integration/29-webtransport-host-meta-json/xmpp-proxy1.toml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
# interfaces to listen for reverse proxy STARTTLS/Direct TLS XMPP connections on, should be open to the internet
|
||||||
|
# incoming_listen = [ "0.0.0.0:5281" ]
|
||||||
|
# interfaces to listen for reverse proxy QUIC XMPP connections on, should be open to the internet
|
||||||
|
quic_listen = [ "0.0.0.0:443" ]
|
||||||
|
# interfaces to listen for outgoing proxy TCP XMPP connections on, should be localhost
|
||||||
|
outgoing_listen = [ "0.0.0.0:15270" ]
|
||||||
|
|
||||||
|
# these ports shouldn't do any TLS, but should assume any connection from xmpp-proxy is secure
|
||||||
|
# prosody module: https://modules.prosody.im/mod_secure_interfaces.html
|
||||||
|
|
||||||
|
# c2s port backend XMPP server listens on
|
||||||
|
c2s_target = "192.5.0.20:15222"
|
||||||
|
|
||||||
|
# s2s port backend XMPP server listens on
|
||||||
|
s2s_target = "192.5.0.20:15269"
|
||||||
|
|
||||||
|
# send PROXYv1 header to backend XMPP server
|
||||||
|
# https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
|
||||||
|
# prosody module: https://modules.prosody.im/mod_net_proxy.html
|
||||||
|
# ejabberd config: https://docs.ejabberd.im/admin/configuration/listen-options/#use-proxy-protocol
|
||||||
|
proxy = true
|
||||||
|
|
||||||
|
# limit incoming stanzas to this many bytes, default to ejabberd's default
|
||||||
|
# https://github.com/processone/ejabberd/blob/master/ejabberd.yml.example#L32
|
||||||
|
# xmpp-proxy will use this many bytes + 16k per connection
|
||||||
|
max_stanza_size_bytes = 262_144
|
||||||
|
|
||||||
|
# TLS key/certificate valid for all your XMPP domains, PEM format
|
||||||
|
# included systemd unit can only read files from /etc/xmpp-proxy/ so put them in there
|
||||||
|
tls_key = "/etc/prosody/certs/xp1.example.org.key"
|
||||||
|
tls_cert = "/etc/prosody/certs/xp1.example.org.crt"
|
||||||
|
|
||||||
|
# configure logging, defaults are commented
|
||||||
|
# can also set env variables XMPP_PROXY_LOG_LEVEL and/or XMPP_PROXY_LOG_STYLE, but values in this file override them
|
||||||
|
# many options, trace is XML-console-level, refer to: https://docs.rs/env_logger/0.8.3/env_logger/#enabling-logging
|
||||||
|
#log_level = "info"
|
||||||
|
# for development/debugging:
|
||||||
|
log_level = "info,xmpp_proxy=trace"
|
||||||
|
|
||||||
|
# one of auto, always, never, refer to: https://docs.rs/env_logger/0.8.3/env_logger/#disabling-colors
|
||||||
|
#log_style = "never"
|
42
integration/29-webtransport-host-meta-json/xmpp-proxy2.toml
Normal file
42
integration/29-webtransport-host-meta-json/xmpp-proxy2.toml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
# interfaces to listen for reverse proxy STARTTLS/Direct TLS XMPP connections on, should be open to the internet
|
||||||
|
# incoming_listen = [ "0.0.0.0:5281" ]
|
||||||
|
# interfaces to listen for reverse proxy QUIC XMPP connections on, should be open to the internet
|
||||||
|
quic_listen = [ "0.0.0.0:443" ]
|
||||||
|
# interfaces to listen for outgoing proxy TCP XMPP connections on, should be localhost
|
||||||
|
outgoing_listen = [ "0.0.0.0:15270" ]
|
||||||
|
|
||||||
|
# these ports shouldn't do any TLS, but should assume any connection from xmpp-proxy is secure
|
||||||
|
# prosody module: https://modules.prosody.im/mod_secure_interfaces.html
|
||||||
|
|
||||||
|
# c2s port backend XMPP server listens on
|
||||||
|
c2s_target = "192.5.0.30:15222"
|
||||||
|
|
||||||
|
# s2s port backend XMPP server listens on
|
||||||
|
s2s_target = "192.5.0.30:15269"
|
||||||
|
|
||||||
|
# send PROXYv1 header to backend XMPP server
|
||||||
|
# https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
|
||||||
|
# prosody module: https://modules.prosody.im/mod_net_proxy.html
|
||||||
|
# ejabberd config: https://docs.ejabberd.im/admin/configuration/listen-options/#use-proxy-protocol
|
||||||
|
proxy = true
|
||||||
|
|
||||||
|
# limit incoming stanzas to this many bytes, default to ejabberd's default
|
||||||
|
# https://github.com/processone/ejabberd/blob/master/ejabberd.yml.example#L32
|
||||||
|
# xmpp-proxy will use this many bytes + 16k per connection
|
||||||
|
max_stanza_size_bytes = 262_144
|
||||||
|
|
||||||
|
# TLS key/certificate valid for all your XMPP domains, PEM format
|
||||||
|
# included systemd unit can only read files from /etc/xmpp-proxy/ so put them in there
|
||||||
|
tls_key = "/etc/prosody/certs/xp2.example.org.key"
|
||||||
|
tls_cert = "/etc/prosody/certs/xp2.example.org.crt"
|
||||||
|
|
||||||
|
# configure logging, defaults are commented
|
||||||
|
# can also set env variables XMPP_PROXY_LOG_LEVEL and/or XMPP_PROXY_LOG_STYLE, but values in this file override them
|
||||||
|
# many options, trace is XML-console-level, refer to: https://docs.rs/env_logger/0.8.3/env_logger/#enabling-logging
|
||||||
|
#log_level = "info"
|
||||||
|
# for development/debugging:
|
||||||
|
log_level = "info,xmpp_proxy=trace"
|
||||||
|
|
||||||
|
# one of auto, always, never, refer to: https://docs.rs/env_logger/0.8.3/env_logger/#disabling-colors
|
||||||
|
#log_style = "never"
|
44
integration/29-webtransport-host-meta-json/xmpp-proxy3.toml
Normal file
44
integration/29-webtransport-host-meta-json/xmpp-proxy3.toml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
# interfaces to listen for reverse proxy STARTTLS/Direct TLS XMPP connections on, should be open to the internet
|
||||||
|
incoming_listen = [ ]
|
||||||
|
# interfaces to listen for reverse proxy QUIC XMPP connections on, should be open to the internet
|
||||||
|
quic_listen = [ ]
|
||||||
|
# interfaces to listen for reverse proxy TLS WebSocket (wss) XMPP connections on, should be open to the internet
|
||||||
|
websocket_listen = [ ]
|
||||||
|
# interfaces to listen for outgoing proxy TCP XMPP connections on, should be localhost
|
||||||
|
outgoing_listen = [ "0.0.0.0:5222" ]
|
||||||
|
|
||||||
|
# these ports shouldn't do any TLS, but should assume any connection from xmpp-proxy is secure
|
||||||
|
# prosody module: https://modules.prosody.im/mod_secure_interfaces.html
|
||||||
|
|
||||||
|
# c2s port backend XMPP server listens on
|
||||||
|
c2s_target = "127.0.0.1:15222"
|
||||||
|
|
||||||
|
# s2s port backend XMPP server listens on
|
||||||
|
s2s_target = "127.0.0.1:15269"
|
||||||
|
|
||||||
|
# send PROXYv1 header to backend XMPP server
|
||||||
|
# https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
|
||||||
|
# prosody module: https://modules.prosody.im/mod_net_proxy.html
|
||||||
|
# ejabberd config: https://docs.ejabberd.im/admin/configuration/listen-options/#use-proxy-protocol
|
||||||
|
proxy = true
|
||||||
|
|
||||||
|
# limit incoming stanzas to this many bytes, default to ejabberd's default
|
||||||
|
# https://github.com/processone/ejabberd/blob/master/ejabberd.yml.example#L32
|
||||||
|
# xmpp-proxy will use this many bytes + 16k per connection
|
||||||
|
max_stanza_size_bytes = 262_144
|
||||||
|
|
||||||
|
# TLS key/certificate valid for all your XMPP domains, PEM format
|
||||||
|
# included systemd unit can only read files from /etc/xmpp-proxy/ so put them in there
|
||||||
|
tls_key = "/etc/certs/rsa/one.example.org.key"
|
||||||
|
tls_cert = "/etc/certs/rsa/one.example.org.crt"
|
||||||
|
|
||||||
|
# configure logging, defaults are commented
|
||||||
|
# can also set env variables XMPP_PROXY_LOG_LEVEL and/or XMPP_PROXY_LOG_STYLE, but values in this file override them
|
||||||
|
# many options, trace is XML-console-level, refer to: https://docs.rs/env_logger/0.8.3/env_logger/#enabling-logging
|
||||||
|
#log_level = "info"
|
||||||
|
# for development/debugging:
|
||||||
|
log_level = "info,xmpp_proxy=trace"
|
||||||
|
|
||||||
|
# one of auto, always, never, refer to: https://docs.rs/env_logger/0.8.3/env_logger/#disabling-colors
|
||||||
|
#log_style = "never"
|
@ -39,24 +39,35 @@ pub fn server_config(certs_key: Arc<CertsKey>) -> Result<ServerConfig> {
|
|||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "s2s-incoming"))]
|
#[cfg(not(any(feature = "s2s-incoming", feature = "webtransport")))]
|
||||||
pub type ServerCerts = ();
|
pub type ServerCerts = ();
|
||||||
|
|
||||||
#[cfg(feature = "s2s-incoming")]
|
#[cfg(any(feature = "s2s-incoming", feature = "webtransport"))]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum ServerCerts {
|
pub enum ServerCerts {
|
||||||
Tls(&'static ServerConnection),
|
Tls(&'static ServerConnection),
|
||||||
#[cfg(feature = "quic")]
|
#[cfg(feature = "quic")]
|
||||||
Quic(Arc<quinn::Connection>),
|
Quic(Option<Vec<Certificate>>, Option<String>, Option<Vec<u8>>), // todo: wrap this in arc or something now
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "s2s-incoming")]
|
#[cfg(any(feature = "s2s-incoming", feature = "webtransport"))]
|
||||||
impl ServerCerts {
|
impl ServerCerts {
|
||||||
|
#[cfg(feature = "quic")]
|
||||||
|
pub fn quic(conn: &quinn::Connection) -> ServerCerts {
|
||||||
|
let certs = conn.peer_identity().and_then(|v| v.downcast::<Vec<Certificate>>().ok()).map(|v| v.to_vec());
|
||||||
|
let (sni, alpn) = conn
|
||||||
|
.handshake_data()
|
||||||
|
.and_then(|v| v.downcast::<quinn::crypto::rustls::HandshakeData>().ok())
|
||||||
|
.map(|h| (h.server_name, h.protocol))
|
||||||
|
.unwrap_or_default();
|
||||||
|
ServerCerts::Quic(certs, sni, alpn)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn peer_certificates(&self) -> Option<Vec<Certificate>> {
|
pub fn peer_certificates(&self) -> Option<Vec<Certificate>> {
|
||||||
match self {
|
match self {
|
||||||
ServerCerts::Tls(c) => c.peer_certificates().map(|c| c.to_vec()),
|
ServerCerts::Tls(c) => c.peer_certificates().map(|c| c.to_vec()),
|
||||||
#[cfg(feature = "quic")]
|
#[cfg(feature = "quic")]
|
||||||
ServerCerts::Quic(c) => c.peer_identity().and_then(|v| v.downcast::<Vec<Certificate>>().ok()).map(|v| v.to_vec()),
|
ServerCerts::Quic(certs, _, _) => certs.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +75,7 @@ impl ServerCerts {
|
|||||||
match self {
|
match self {
|
||||||
ServerCerts::Tls(c) => c.server_name().map(|s| s.to_string()),
|
ServerCerts::Tls(c) => c.server_name().map(|s| s.to_string()),
|
||||||
#[cfg(feature = "quic")]
|
#[cfg(feature = "quic")]
|
||||||
ServerCerts::Quic(c) => c.handshake_data().and_then(|v| v.downcast::<quinn::crypto::rustls::HandshakeData>().ok()).and_then(|h| h.server_name),
|
ServerCerts::Quic(_, sni, _) => sni.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +83,7 @@ impl ServerCerts {
|
|||||||
match self {
|
match self {
|
||||||
ServerCerts::Tls(c) => c.alpn_protocol().map(|s| s.to_vec()),
|
ServerCerts::Tls(c) => c.alpn_protocol().map(|s| s.to_vec()),
|
||||||
#[cfg(feature = "quic")]
|
#[cfg(feature = "quic")]
|
||||||
ServerCerts::Quic(c) => c.handshake_data().and_then(|v| v.downcast::<quinn::crypto::rustls::HandshakeData>().ok()).and_then(|h| h.protocol),
|
ServerCerts::Quic(_, _, alpn) => alpn.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +91,7 @@ impl ServerCerts {
|
|||||||
match self {
|
match self {
|
||||||
ServerCerts::Tls(_) => true,
|
ServerCerts::Tls(_) => true,
|
||||||
#[cfg(feature = "quic")]
|
#[cfg(feature = "quic")]
|
||||||
ServerCerts::Quic(_) => false,
|
ServerCerts::Quic(_, _, _) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,13 @@ impl OutgoingConfig {
|
|||||||
_ => ClientConfig::builder().with_safe_defaults().with_custom_certificate_verifier(cert_verifier).with_no_client_auth(),
|
_ => ClientConfig::builder().with_safe_defaults().with_custom_certificate_verifier(cert_verifier).with_no_client_auth(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "webtransport")]
|
||||||
|
let config_webtransport_alpn = {
|
||||||
|
let mut config = config.clone();
|
||||||
|
config.alpn_protocols.push(webtransport_quinn::ALPN.to_vec());
|
||||||
|
Arc::new(config)
|
||||||
|
};
|
||||||
|
|
||||||
let mut config_alpn = config.clone();
|
let mut config_alpn = config.clone();
|
||||||
config_alpn.alpn_protocols.push(if is_c2s { ALPN_XMPP_CLIENT } else { ALPN_XMPP_SERVER }.to_vec());
|
config_alpn.alpn_protocols.push(if is_c2s { ALPN_XMPP_CLIENT } else { ALPN_XMPP_SERVER }.to_vec());
|
||||||
|
|
||||||
@ -30,6 +37,8 @@ impl OutgoingConfig {
|
|||||||
|
|
||||||
OutgoingVerifierConfig {
|
OutgoingVerifierConfig {
|
||||||
max_stanza_size_bytes: self.max_stanza_size_bytes,
|
max_stanza_size_bytes: self.max_stanza_size_bytes,
|
||||||
|
#[cfg(feature = "webtransport")]
|
||||||
|
config_webtransport_alpn,
|
||||||
config_alpn,
|
config_alpn,
|
||||||
connector_alpn,
|
connector_alpn,
|
||||||
connector,
|
connector,
|
||||||
@ -41,6 +50,9 @@ impl OutgoingConfig {
|
|||||||
pub struct OutgoingVerifierConfig {
|
pub struct OutgoingVerifierConfig {
|
||||||
pub max_stanza_size_bytes: usize,
|
pub max_stanza_size_bytes: usize,
|
||||||
|
|
||||||
|
#[cfg(feature = "webtransport")]
|
||||||
|
pub config_webtransport_alpn: Arc<ClientConfig>,
|
||||||
|
|
||||||
pub config_alpn: Arc<ClientConfig>,
|
pub config_alpn: Arc<ClientConfig>,
|
||||||
pub connector_alpn: TlsConnector,
|
pub connector_alpn: TlsConnector,
|
||||||
|
|
||||||
|
@ -17,6 +17,9 @@ pub mod srv;
|
|||||||
#[cfg(feature = "websocket")]
|
#[cfg(feature = "websocket")]
|
||||||
pub mod websocket;
|
pub mod websocket;
|
||||||
|
|
||||||
|
#[cfg(feature = "webtransport")]
|
||||||
|
pub mod webtransport;
|
||||||
|
|
||||||
#[cfg(any(feature = "s2s-incoming", feature = "outgoing"))]
|
#[cfg(any(feature = "s2s-incoming", feature = "outgoing"))]
|
||||||
pub mod verify;
|
pub mod verify;
|
||||||
|
|
||||||
|
@ -36,26 +36,21 @@ fn internal_spawn_quic_listener(incoming: Endpoint, local_addr: SocketAddr, conf
|
|||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Ok(new_conn) = incoming_conn.await {
|
if let Ok(new_conn) = incoming_conn.await {
|
||||||
let client_addr = Context::new("quic-in", new_conn.remote_address());
|
let client_addr = Context::new("quic-in", new_conn.remote_address());
|
||||||
|
|
||||||
let new_conn = Arc::new(new_conn);
|
|
||||||
#[cfg(feature = "s2s-incoming")]
|
|
||||||
let server_certs = ServerCerts::Quic(new_conn.clone());
|
|
||||||
#[cfg(not(feature = "s2s-incoming"))]
|
|
||||||
let server_certs = ();
|
|
||||||
|
|
||||||
info!("{} connected new connection", client_addr.log_from());
|
info!("{} connected new connection", client_addr.log_from());
|
||||||
|
|
||||||
while let Ok((wrt, rd)) = new_conn.accept_bi().await {
|
#[cfg(any(feature = "s2s-incoming", feature = "webtransport"))]
|
||||||
let config = config.clone();
|
let server_certs = {
|
||||||
let mut client_addr = client_addr.clone();
|
let server_certs = ServerCerts::quic(&new_conn);
|
||||||
let server_certs = server_certs.clone();
|
#[cfg(feature = "webtransport")]
|
||||||
info!("{} connected new stream", client_addr.log_from());
|
if server_certs.alpn().map(|a| a == webtransport_quinn::ALPN).unwrap_or(false) {
|
||||||
tokio::spawn(async move {
|
return crate::webtransport::incoming::handle_webtransport_session(new_conn, config, server_certs, local_addr, client_addr).await;
|
||||||
if let Err(e) = shuffle_rd_wr(StanzaRead::new(rd), StanzaWrite::new(wrt), config, server_certs, local_addr, &mut client_addr).await {
|
}
|
||||||
error!("{} {}", client_addr.log_from(), e);
|
server_certs
|
||||||
}
|
};
|
||||||
});
|
#[cfg(not(any(feature = "s2s-incoming", feature = "webtransport")))]
|
||||||
}
|
let server_certs = ();
|
||||||
|
|
||||||
|
handle_quic_session(new_conn, config, server_certs, local_addr, client_addr).await
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -64,7 +59,23 @@ fn internal_spawn_quic_listener(incoming: Endpoint, local_addr: SocketAddr, conf
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn quic_server_config(server_config: rustls::ServerConfig) -> ServerConfig {
|
pub async fn handle_quic_session(conn: quinn::Connection, config: Arc<IncomingConfig>, server_certs: ServerCerts, local_addr: SocketAddr, client_addr: Context<'static>) {
|
||||||
|
while let Ok((wrt, rd)) = conn.accept_bi().await {
|
||||||
|
let config = config.clone();
|
||||||
|
let mut client_addr = client_addr.clone();
|
||||||
|
let server_certs = server_certs.clone();
|
||||||
|
info!("{} connected new stream", client_addr.log_from());
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = shuffle_rd_wr(StanzaRead::new(rd), StanzaWrite::new(wrt), config, server_certs, local_addr, &mut client_addr).await {
|
||||||
|
error!("{} {}", client_addr.log_from(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn quic_server_config(mut server_config: rustls::ServerConfig) -> ServerConfig {
|
||||||
|
#[cfg(feature = "webtransport")]
|
||||||
|
server_config.alpn_protocols.push(webtransport_quinn::ALPN.to_vec());
|
||||||
let transport_config = quinn::TransportConfig::default();
|
let transport_config = quinn::TransportConfig::default();
|
||||||
// todo: configure transport_config here if needed
|
// todo: configure transport_config here if needed
|
||||||
let mut server_config = ServerConfig::with_crypto(Arc::new(server_config));
|
let mut server_config = ServerConfig::with_crypto(Arc::new(server_config));
|
||||||
|
76
src/srv.rs
76
src/srv.rs
@ -13,7 +13,7 @@ use crate::{
|
|||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use data_encoding::BASE64;
|
use data_encoding::BASE64;
|
||||||
use log::{debug, error, trace};
|
use log::{debug, error, trace};
|
||||||
use reqwest::Client;
|
use reqwest::{Client, Url};
|
||||||
use ring::digest::{Algorithm, Context as DigestContext, SHA256, SHA512};
|
use ring::digest::{Algorithm, Context as DigestContext, SHA256, SHA512};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{
|
use std::{
|
||||||
@ -60,7 +60,10 @@ enum XmppConnectionType {
|
|||||||
#[cfg(feature = "quic")]
|
#[cfg(feature = "quic")]
|
||||||
QUIC,
|
QUIC,
|
||||||
#[cfg(feature = "websocket")]
|
#[cfg(feature = "websocket")]
|
||||||
|
// uri, origin
|
||||||
WebSocket(Uri, String),
|
WebSocket(Uri, String),
|
||||||
|
#[cfg(feature = "webtransport")]
|
||||||
|
WebTransport(Url),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XmppConnectionType {
|
impl XmppConnectionType {
|
||||||
@ -69,11 +72,13 @@ impl XmppConnectionType {
|
|||||||
#[cfg(feature = "quic")]
|
#[cfg(feature = "quic")]
|
||||||
XmppConnectionType::QUIC => 0,
|
XmppConnectionType::QUIC => 0,
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
XmppConnectionType::DirectTLS => 1,
|
XmppConnectionType::DirectTLS => 2,
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
XmppConnectionType::StartTLS => 2,
|
XmppConnectionType::StartTLS => 3,
|
||||||
#[cfg(feature = "websocket")]
|
#[cfg(feature = "websocket")]
|
||||||
XmppConnectionType::WebSocket(_, _) => 3,
|
XmppConnectionType::WebSocket(_, _) => 4,
|
||||||
|
#[cfg(feature = "webtransport")]
|
||||||
|
XmppConnectionType::WebTransport(_) => 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,7 +89,7 @@ impl Ord for XmppConnectionType {
|
|||||||
if cmp != Ordering::Equal {
|
if cmp != Ordering::Equal {
|
||||||
return cmp;
|
return cmp;
|
||||||
}
|
}
|
||||||
// so they are the same type, but WebSocket is a special case...
|
// so they are the same type, but WebSocket and WebTransport is a special case...
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
#[cfg(feature = "websocket")]
|
#[cfg(feature = "websocket")]
|
||||||
(XmppConnectionType::WebSocket(self_uri, self_origin), XmppConnectionType::WebSocket(other_uri, other_origin)) => {
|
(XmppConnectionType::WebSocket(self_uri, self_origin), XmppConnectionType::WebSocket(other_uri, other_origin)) => {
|
||||||
@ -94,6 +99,8 @@ impl Ord for XmppConnectionType {
|
|||||||
}
|
}
|
||||||
self_origin.cmp(other_origin)
|
self_origin.cmp(other_origin)
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "webtransport")]
|
||||||
|
(XmppConnectionType::WebTransport(self_url), XmppConnectionType::WebTransport(other_url)) => self_url.cmp(other_url),
|
||||||
(_, _) => Ordering::Equal,
|
(_, _) => Ordering::Equal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,6 +244,20 @@ impl XmppConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
#[cfg(feature = "webtransport")]
|
||||||
|
XmppConnectionType::WebTransport(ref url) => match crate::webtransport::outgoing::webtransport_connect(to_addr, domain, url, config).await {
|
||||||
|
Ok((wr, rd)) => return Ok((wr, rd, to_addr, "webtransport-out")),
|
||||||
|
Err(e) => {
|
||||||
|
if self.secure && self.target != orig_domain {
|
||||||
|
match crate::webtransport::outgoing::webtransport_connect(to_addr, orig_domain, url, config).await {
|
||||||
|
Ok((wr, rd)) => return Ok((wr, rd, to_addr, "webtransport-out")),
|
||||||
|
Err(e2) => error!("webtransport connection failed to IP {} from URL {}, error try 1: {}, error try 2: {}", to_addr, url, e, e2),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error!("websocket connection failed to IP {} from URL {}, error: {}", to_addr, url, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bail!("cannot connect to any IPs for SRV: {}", self.target)
|
bail!("cannot connect to any IPs for SRV: {}", self.target)
|
||||||
@ -301,6 +322,21 @@ fn wss_to_srv(url: &str, secure: bool) -> Option<XmppConnection> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "webtransport")]
|
||||||
|
fn wt_to_srv(url: &str) -> Option<(XmppConnectionType, u16)> {
|
||||||
|
let url = match Url::parse(url) {
|
||||||
|
Ok(url) => url,
|
||||||
|
Err(e) => {
|
||||||
|
debug!("invalid URL record '{}': {}", url, e);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let port = if let Some(port) = url.port() { port } else { 443 };
|
||||||
|
|
||||||
|
Some((XmppConnectionType::WebTransport(url), port))
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "websocket")]
|
#[cfg(feature = "websocket")]
|
||||||
fn collect_txts(ret: &mut Vec<XmppConnection>, txt_records: std::result::Result<TxtLookup, ResolveError>, is_c2s: bool) {
|
fn collect_txts(ret: &mut Vec<XmppConnection>, txt_records: std::result::Result<TxtLookup, ResolveError>, is_c2s: bool) {
|
||||||
if let Ok(txt_records) = txt_records {
|
if let Ok(txt_records) = txt_records {
|
||||||
@ -534,6 +570,12 @@ enum Link {
|
|||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
link: Option<LinkCommon>,
|
link: Option<LinkCommon>,
|
||||||
},
|
},
|
||||||
|
#[serde(rename = "urn:xmpp:alt-connections:webtransport")]
|
||||||
|
WebTransport {
|
||||||
|
href: String,
|
||||||
|
#[serde(flatten)]
|
||||||
|
link: LinkCommon,
|
||||||
|
},
|
||||||
#[serde(rename = "urn:xmpp:alt-connections:tls")]
|
#[serde(rename = "urn:xmpp:alt-connections:tls")]
|
||||||
DirectTLS {
|
DirectTLS {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
@ -546,6 +588,12 @@ enum Link {
|
|||||||
link: LinkCommon,
|
link: LinkCommon,
|
||||||
port: u16,
|
port: u16,
|
||||||
},
|
},
|
||||||
|
#[serde(rename = "urn:xmpp:alt-connections:s2s-webtransport")]
|
||||||
|
S2SWebTransport {
|
||||||
|
href: String,
|
||||||
|
#[serde(flatten)]
|
||||||
|
link: LinkCommon,
|
||||||
|
},
|
||||||
#[serde(rename = "urn:xmpp:alt-connections:s2s-websocket")]
|
#[serde(rename = "urn:xmpp:alt-connections:s2s-websocket")]
|
||||||
S2SWebSocket {
|
S2SWebSocket {
|
||||||
href: String,
|
href: String,
|
||||||
@ -630,6 +678,24 @@ impl Link {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "webtransport")]
|
||||||
|
Link::WebTransport { href, link } => {
|
||||||
|
return if is_c2s {
|
||||||
|
let (conn_type, port) = wt_to_srv(&href)?;
|
||||||
|
link.into_xmpp_connection(conn_type, port)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#[cfg(feature = "webtransport")]
|
||||||
|
Link::S2SWebTransport { href, link } => {
|
||||||
|
return if !is_c2s {
|
||||||
|
let (conn_type, port) = wt_to_srv(&href)?;
|
||||||
|
link.into_xmpp_connection(conn_type, port)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
@ -127,12 +127,12 @@ pub async fn handle_tls_connection<S: AsyncReadWritePeekSplit>(mut stream: S, cl
|
|||||||
// where we read the first stanza, where we are guaranteed the handshake is complete, but I can't
|
// where we read the first stanza, where we are guaranteed the handshake is complete, but I can't
|
||||||
// do that without ignoring the lifetime and just pulling a C programmer and pinky promising to be
|
// do that without ignoring the lifetime and just pulling a C programmer and pinky promising to be
|
||||||
// *very careful* that this reference doesn't outlive stream...
|
// *very careful* that this reference doesn't outlive stream...
|
||||||
#[cfg(feature = "s2s-incoming")]
|
#[cfg(any(feature = "s2s-incoming", feature = "webtransport"))]
|
||||||
let server_certs = {
|
let server_certs = {
|
||||||
let server_connection: &'static ServerConnection = unsafe { std::mem::transmute(server_connection) };
|
let server_connection: &'static ServerConnection = unsafe { std::mem::transmute(server_connection) };
|
||||||
ServerCerts::Tls(server_connection)
|
ServerCerts::Tls(server_connection)
|
||||||
};
|
};
|
||||||
#[cfg(not(feature = "s2s-incoming"))]
|
#[cfg(not(any(feature = "s2s-incoming", feature = "webtransport")))]
|
||||||
let server_certs = ();
|
let server_certs = ();
|
||||||
|
|
||||||
#[cfg(not(feature = "websocket"))]
|
#[cfg(not(feature = "websocket"))]
|
||||||
|
44
src/webtransport/incoming.rs
Normal file
44
src/webtransport/incoming.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
use crate::{
|
||||||
|
common::incoming::{shuffle_rd_wr, IncomingConfig, ServerCerts},
|
||||||
|
context::Context,
|
||||||
|
in_out::{StanzaRead, StanzaWrite},
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::{error, info};
|
||||||
|
use std::{net::SocketAddr, sync::Arc};
|
||||||
|
|
||||||
|
pub async fn handle_webtransport_session(conn: quinn::Connection, config: Arc<IncomingConfig>, server_certs: ServerCerts, local_addr: SocketAddr, mut client_addr: Context<'static>) {
|
||||||
|
client_addr.set_proto("webtransport-in");
|
||||||
|
|
||||||
|
// Perform the WebTransport handshake.
|
||||||
|
let request = match webtransport_quinn::accept(conn).await {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(e) => {
|
||||||
|
error!("{} {}", client_addr.log_from(), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
info!("{} received request URL: {}", client_addr.log_from(), request.url());
|
||||||
|
|
||||||
|
// Accept the session.
|
||||||
|
let session = match request.ok().await {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(e) => {
|
||||||
|
error!("{} {}", client_addr.log_from(), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
info!("{} connected new session", client_addr.log_from());
|
||||||
|
|
||||||
|
while let Ok((wrt, rd)) = session.accept_bi().await {
|
||||||
|
let config = config.clone();
|
||||||
|
let mut client_addr = client_addr.clone();
|
||||||
|
let server_certs = server_certs.clone();
|
||||||
|
info!("{} connected new stream", client_addr.log_from());
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = shuffle_rd_wr(StanzaRead::new(rd), StanzaWrite::new(wrt), config, server_certs, local_addr, &mut client_addr).await {
|
||||||
|
error!("{} {}", client_addr.log_from(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
5
src/webtransport/mod.rs
Normal file
5
src/webtransport/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#[cfg(feature = "incoming")]
|
||||||
|
pub mod incoming;
|
||||||
|
|
||||||
|
#[cfg(feature = "outgoing")]
|
||||||
|
pub mod outgoing;
|
26
src/webtransport/outgoing.rs
Normal file
26
src/webtransport/outgoing.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
common::outgoing::OutgoingVerifierConfig,
|
||||||
|
in_out::{StanzaRead, StanzaWrite},
|
||||||
|
};
|
||||||
|
use anyhow::Result;
|
||||||
|
use log::trace;
|
||||||
|
use reqwest::Url;
|
||||||
|
|
||||||
|
pub async fn webtransport_connect(target: SocketAddr, server_name: &str, url: &Url, config: &OutgoingVerifierConfig) -> Result<(StanzaWrite, StanzaRead)> {
|
||||||
|
let bind_addr = "0.0.0.0:0".parse().unwrap();
|
||||||
|
|
||||||
|
let mut endpoint = quinn::Endpoint::client(bind_addr)?;
|
||||||
|
endpoint.set_default_client_config(quinn::ClientConfig::new(config.config_webtransport_alpn.clone()));
|
||||||
|
|
||||||
|
// connect to server
|
||||||
|
let connection = endpoint.connect(target, server_name)?.await?;
|
||||||
|
trace!("quic pre-wt connected: addr={}", connection.remote_address());
|
||||||
|
|
||||||
|
let connection = webtransport_quinn::connect_with(connection, url).await?;
|
||||||
|
trace!("webtransport connected: addr={}", connection.remote_address());
|
||||||
|
|
||||||
|
let (wrt, rd) = connection.open_bi().await?;
|
||||||
|
Ok((StanzaWrite::new(wrt), StanzaRead::new(rd)))
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
# interfaces to listen for reverse proxy STARTTLS/Direct TLS/TLS WebSocket (wss) XMPP connections on, should be open to the internet
|
# interfaces to listen for reverse proxy STARTTLS/Direct TLS/TLS WebSocket (wss) XMPP connections on, should be open to the internet
|
||||||
incoming_listen = [ "0.0.0.0:5222", "0.0.0.0:5269", "0.0.0.0:443" ]
|
incoming_listen = [ "0.0.0.0:5222", "0.0.0.0:5269", "0.0.0.0:443" ]
|
||||||
# interfaces to listen for reverse proxy QUIC XMPP connections on, should be open to the internet
|
# interfaces to listen for reverse proxy QUIC/WebTransport XMPP connections on, should be open to the internet
|
||||||
quic_listen = [ "0.0.0.0:443" ]
|
quic_listen = [ "0.0.0.0:443" ]
|
||||||
# interfaces to listen for outgoing proxy TCP or WebSocket XMPP connections on, should be localhost or a path for a unix socket
|
# interfaces to listen for outgoing proxy TCP or WebSocket XMPP connections on, should be localhost or a path for a unix socket
|
||||||
outgoing_listen = [ "127.0.0.1:15270" ]
|
outgoing_listen = [ "127.0.0.1:15270" ]
|
||||||
@ -39,4 +39,4 @@ tls_cert = "/etc/xmpp-proxy/fullchain.cer"
|
|||||||
#log_level = "info,xmpp_proxy=trace"
|
#log_level = "info,xmpp_proxy=trace"
|
||||||
|
|
||||||
# one of auto, always, never, refer to: https://docs.rs/env_logger/0.8.3/env_logger/#disabling-colors
|
# one of auto, always, never, refer to: https://docs.rs/env_logger/0.8.3/env_logger/#disabling-colors
|
||||||
#log_style = "never"
|
#log_style = "never"
|
||||||
|
Loading…
Reference in New Issue
Block a user