Add support for running behind firewall and NAT

This commit is contained in:
Jonas Herzig 2019-02-09 10:40:38 +01:00
parent 20848303e9
commit a194bb6c6f
5 changed files with 137 additions and 20 deletions

73
Cargo.lock generated
View file

@ -74,7 +74,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "block-buffer"
version = "0.7.2"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -291,11 +291,53 @@ dependencies = [
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gio-sys"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "glib"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "glib-sys"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "glob"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "gobject-sys"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "handy_async"
version = "0.2.13"
@ -381,21 +423,28 @@ dependencies = [
[[package]]
name = "libnice"
version = "0.1.0"
source = "git+https://github.com/johni0702/rust-libnice?rev=f60d748#f60d748c03ef1027e95e82a09a2beba7c98bb32d"
source = "git+https://github.com/johni0702/rust-libnice?rev=1053c81#1053c81b549011b783dd33c1ce7967477800b783"
dependencies = [
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libnice-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"libnice-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"webrtc-sdp 0.1.0 (git+https://github.com/nils-ohlmeier/rsdparsa/?rev=ccf6249)",
]
[[package]]
name = "libnice-sys"
version = "0.1.0"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bindgen 0.42.3 (registry+https://github.com/rust-lang/crates.io-index)",
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -495,7 +544,7 @@ dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libnice 0.1.0 (git+https://github.com/johni0702/rust-libnice?rev=f60d748)",
"libnice 0.1.0 (git+https://github.com/johni0702/rust-libnice?rev=1053c81)",
"mumble-protocol 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)",
@ -987,7 +1036,7 @@ name = "sha-1"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1469,7 +1518,7 @@ dependencies = [
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
"checksum bindgen 0.42.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e0f199ccbabf5e9f9e13a3096534e80c9ce37aee440789dafaa47190e283245c"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "509de513cca6d92b6aacf9c61acfe7eaa160837323a81068d690cc1f8e5740da"
"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d"
"checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591"
"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
@ -1497,7 +1546,11 @@ dependencies = [
"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592"
"checksum gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6975ada29f7924dc1c90b30ed3b32d777805a275556c05e420da4fbdc22eb250"
"checksum glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a333edf5b9f1411c246ef14e7881b087255f04c56dbef48c64a0cb039b4b340"
"checksum glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3573351e846caed9f11207b275cd67bc07f0c2c94fb628e5d7c92ca056c7882d"
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
"checksum gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08475e4a08f27e6e2287005950114735ed61cec2cb8c1187682a5aec8c69b715"
"checksum handy_async 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "165d5c5434dd3b9b3b3fa7ad58a895f13ee34f9aa42f3e5d13bc0ac544be7232"
"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83"
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
@ -1509,8 +1562,8 @@ dependencies = [
"checksum lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddba4c30a78328befecec92fc94970e53b3ae385827d28620f0f5bb2493081e0"
"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311"
"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2"
"checksum libnice 0.1.0 (git+https://github.com/johni0702/rust-libnice?rev=f60d748)" = "<none>"
"checksum libnice-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c14f86d71d491b61486e5609bc6d5c5acf5d3f34e399b4881dde51c3e53f7cd"
"checksum libnice 0.1.0 (git+https://github.com/johni0702/rust-libnice?rev=1053c81)" = "<none>"
"checksum libnice-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4076d4216144459cf21253dd351471bb58e0cbbb0e47f93768bb7d4428ccb149"
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"

View file

@ -18,7 +18,7 @@ tokio-tungstenite = "0.6"
tungstenite = "0.6"
rtp = { git = "https://github.com/johni0702/rtp", rev = "ee8be93", features = ["openssl", "tokio"] }
# libnice = "0.2"
libnice = { git = "https://github.com/johni0702/rust-libnice", rev = "f60d748" }
libnice = { git = "https://github.com/johni0702/rust-libnice", rev = "1053c81" }
# webrtc-sdp = "0.2"
webrtc-sdp = { git = "https://github.com/nils-ohlmeier/rsdparsa/", rev = "ccf6249" }
openssl = "0.10"

View file

@ -39,11 +39,9 @@ mumble-web-proxy --listen-ws 64737 --server mumbleserver:64738
```
#### Firewalls or NAT
Note: Not yet implemented.
If your mumble-web-proxy is running behind a firewall or NAT, you need to allocate a range of ports to it which it can use for ICE connection establishment.
```
mumble-web-proxy --listen-ws 64737 --server mumbleserver:64738 --ice-start 20000 --ice-end 21000
mumble-web-proxy --listen-ws 64737 --server mumbleserver:64738 --ice-port-min 20000 --ice-port-max 21000
```
For NATs, you additionally need to provide it with its publicly reachable IP address(es):
```

View file

@ -22,6 +22,7 @@ use rtp::rfc5764::{DtlsSrtp, DtlsSrtpHandshakeResult};
use rtp::traits::{ReadPacket, WritePacket};
use std::collections::BTreeMap;
use std::ffi::CString;
use std::net::IpAddr;
use std::time::{Duration, Instant};
use tokio::io;
use tokio::prelude::*;
@ -30,6 +31,7 @@ use webrtc_sdp::attribute_type::SdpAttribute;
use error::Error;
use utils::EitherS;
use Config;
type SessionId = u32;
@ -82,6 +84,7 @@ impl User {
}
pub struct Connection {
config: Config,
inbound_client: Box<Stream<Item = ControlPacket<Serverbound>, Error = Error>>,
outbound_client: Box<Sink<SinkItem = ControlPacket<Clientbound>, SinkError = Error>>,
inbound_server: Box<Stream<Item = ControlPacket<Clientbound>, Error = Error>>,
@ -109,6 +112,7 @@ pub struct Connection {
impl Connection {
pub fn new<CSi, CSt, SSi, SSt>(
config: Config,
client_sink: CSi,
client_stream: CSt,
server_sink: SSi,
@ -135,6 +139,7 @@ impl Connection {
let cert = cert_builder.build();
Self {
config,
inbound_client: Box::new(client_stream),
outbound_client: Box::new(client_sink),
inbound_server: Box::new(server_stream),
@ -192,7 +197,13 @@ impl Connection {
agent.set_software("mumble-web-proxy");
// Setup ICE stream
let mut stream = match agent.stream_builder(1).build() {
let mut stream = match {
let mut builder = agent.stream_builder(1);
if self.config.min_port != 1 || self.config.max_port != u16::max_value() {
builder.set_port_range(self.config.min_port, self.config.max_port);
}
builder.build()
} {
Ok(stream) => stream,
Err(err) => {
return stream::once(Err(io::Error::new(io::ErrorKind::Other, err).into()));
@ -531,12 +542,24 @@ impl Future for Connection {
// Poll ice stream for new candidates
if let Some((_, stream)) = &mut self.ice {
if let Async::Ready(Some(candidate)) = stream.poll()? {
let candidate = format!("candidate:{}", candidate.to_string());
println!("Local ice candidate: {}", candidate);
if let Async::Ready(Some(mut candidate)) = stream.poll()? {
println!("Local ice candidate: {}", candidate.to_string());
// Map to public addresses (if configured)
let config = &self.config;
match (&mut candidate.address, config.public_v4, config.public_v6) {
(IpAddr::V4(addr), Some(public), _) => {
*addr = public;
}
(IpAddr::V6(addr), _, Some(public)) => {
*addr = public;
}
_ => {} // non configured
};
// Got a new candidate, send it to the client
let mut msg = msgs::IceCandidate::new();
msg.set_content(candidate.to_string());
msg.set_content(format!("candidate:{}", candidate.to_string()));
let frame = Frame::Client(msg.into());
self.stream_to_be_sent = Some(Box::new(stream::once(Ok(frame))));
continue 'poll;

View file

@ -19,6 +19,7 @@ extern crate tokio_tungstenite;
extern crate tungstenite;
extern crate webrtc_sdp;
use argparse::StoreOption;
use argparse::StoreTrue;
use argparse::{ArgumentParser, Store};
use byteorder::{BigEndian, ByteOrder};
@ -30,6 +31,7 @@ use mumble_protocol::control::RawControlPacket;
use mumble_protocol::Clientbound;
use std::convert::Into;
use std::convert::TryInto;
use std::net::Ipv4Addr;
use std::net::Ipv6Addr;
use std::net::ToSocketAddrs;
use tokio::net::TcpListener;
@ -48,10 +50,24 @@ mod utils;
use connection::Connection;
use error::Error;
#[derive(Debug, Clone)]
pub struct Config {
pub min_port: u16,
pub max_port: u16,
pub public_v4: Option<Ipv4Addr>,
pub public_v6: Option<Ipv6Addr>,
}
fn main() {
let mut ws_port = 0_u16;
let mut upstream = "".to_string();
let mut accept_invalid_certs = false;
let mut config = Config {
min_port: 1,
max_port: u16::max_value(),
public_v4: None,
public_v6: None,
};
{
let mut ap = ArgumentParser::new();
@ -76,6 +92,26 @@ fn main() {
"Connect to upstream server even when its certificate is invalid.
Only ever use this if know that your server is using a self-signed certificate!",
);
ap.refer(&mut config.min_port).add_option(
&["--ice-port-min"],
Store,
"Minimum port number to use for ICE host candidates.",
);
ap.refer(&mut config.max_port).add_option(
&["--ice-port-max"],
Store,
"Maximum port number to use for ICE host candidates.",
);
ap.refer(&mut config.public_v4).add_option(
&["--ice-ipv4"],
StoreOption,
"Set a public IPv4 address to be used for ICE host candidates.",
);
ap.refer(&mut config.public_v6).add_option(
&["--ice-ipv6"],
StoreOption,
"Set a public IPv6 address to be used for ICE host candidates.",
);
ap.parse_args_or_exit();
}
@ -138,6 +174,7 @@ fn main() {
.from_err();
// Once both are done, begin proxy duty
let config = config.clone();
let f = client
.join(server)
.and_then(move |(client, server)| {
@ -164,7 +201,13 @@ fn main() {
let server_sink = server_sink.sink_from_err();
let server_stream = server_stream.from_err();
Connection::new(client_sink, client_stream, server_sink, server_stream)
Connection::new(
config,
client_sink,
client_stream,
server_sink,
server_stream,
)
})
.or_else(move |err| {
if err.is_connection_closed() {