added mirror mode

This commit is contained in:
Ellie D 2019-06-10 16:21:34 -05:00
parent 58bca50c2c
commit 07b1e0eff1
2 changed files with 59 additions and 9 deletions

View File

@ -29,10 +29,13 @@ streams (it will, however, be relayed back to the source).
This behavior can be overridden with "loopback mode" in which Sunbeam always relays data to all
clients and servers except the one which originated the data. Sunbeam automatically goes into
loopback mode if no ports are specified, or if only one port and no addresses are specified. You
can also pass the `-l` flag to require Sunbeam to run in loopback mode.
can also pass the `-l` or `--loopback` flag to require Sunbeam to run in loopback mode.
If you want Sunbeam to send data back to its source in addition to relaying it, you can also
activate "mirror mode" by passing the `-m` or `--mirror` flag at the command line.
General usage looks like the following:
`sunbeam [-l] [local port] [remote address]:[port]`
`sunbeam [flags] [local port]... [remote address]:[port]...`
Sunbeam is capable of using both TCP and UDP for sending and receiving data, and can pass data
between TCP and UDP streams. By default, Sunbeam attempts to use both protocols for every port

View File

@ -22,7 +22,6 @@ static IDLE_MAX:u64 = 65535; // maximum number of idle cycles to count up befo
static RECONNECT_WAIT:u64 = 1000; // time in ms to wait between reconnect attempts
static LOOPBACK_FLAG:&str = "-l"; // flag passed to sunbeam to activate loopback mode
static BLOCKFILE_NAME:&str = ".nosunbeam"; // file to check for as the client blacklist
static ALLOWFILE_NAME:&str = ".yesunbeam"; // file to check for as the client whitelist, for Whitelist-mode connectors
@ -127,7 +126,11 @@ fn load_rules(rulefilepath:&str) -> HashSet<IpAddr> {
fn main() {
let argv = args().collect::<Vec<String>>();
if argv.len() < 2 {
eprintln!("-!- usage: sunbeam [protocol][local port][privacy]... [protocol][remote resource address]:[remote port]...");
eprintln!("-!- usage: sunbeam [flags] [protocol][local port][privacy]... [protocol][remote resource address]:[remote port]...");
eprintln!();
eprintln!(" flags:");
eprintln!(" -l --loopback - also relay data to clients connecting on the same port");
eprintln!(" -m --mirror - also relay data back to its source");
eprintln!();
eprintln!(" prefix ports or addresses with a letter to indicate transport protocol:");
eprintln!(" t - tcp");
@ -141,12 +144,21 @@ fn main() {
exit(1);
}
let mut loopbackmode:bool = false;
let mut mirrormode:bool = false;
let mut addresses:Vec<(PortProtocol,SocketAddr)> = Vec::new();
let mut ports:Vec<(PortProtocol,PortPrivacy,u16)> = Vec::new();
let mut flags:Vec<char> = Vec::new();
let mut switches:Vec<&str> = Vec::new();
for arg in argv[1..].iter() {
if arg == LOOPBACK_FLAG {
loopbackmode = true;
if arg.starts_with("--") {
switches.push(arg.trim_matches('-'));
continue;
} else if arg.starts_with("-") {
for c in arg.trim_matches('-').chars() {
flags.push(c);
}
continue;
}
let strippedarg = arg.trim_end_matches(&PORT_SUFFIXES[..]).trim_start_matches(&PORT_PREFIXES[..]);
match strippedarg.parse::<u16>() {
@ -180,9 +192,32 @@ fn main() {
}
};
}
for flag in flags.iter() {
match flag {
'l' => loopbackmode = true,
'm' => mirrormode = true,
c => {
eprintln!("-!- unrecognized flag character `{}`",c);
exit(1);
},
};
}
for switch in switches.iter() {
match switch {
&"loopback" => loopbackmode = true,
&"mirror" => mirrormode = true,
s => {
eprintln!("-!- unrecognized switch `{}`",s);
exit(1);
},
};
}
loopbackmode |= (addresses.len() == 0 && ports.len() == 1) || (addresses.len() > 0 && ports.len() == 0);
if loopbackmode {
println!("-i- running in loopback mode (relaying data between all connections)");
println!("-i- running in loopback mode (relaying data between all clients)");
}
if mirrormode {
println!("-i- running in mirror mode (also relaying data back to source client)");
}
let blocklist = load_rules(BLOCKFILE_NAME);
@ -358,6 +393,9 @@ fn main() {
broken_tcpsources.push_back(address.clone());
broken = true;
} else {
if mirrormode && n > 0 {
let _ = guest.stream.write_all(&tcp_buffer[..n]);
}
tcp_nrecv = n;
sourceaddress = address.clone();
},
@ -374,9 +412,12 @@ fn main() {
Err(why) => {
eprintln!("-!- failed to receive UDP packets: {}",why);
},
Ok((nrecv,srcaddr)) => {
Ok((n,srcaddr)) => {
if &srcaddr == address {
udp_nrecv = nrecv;
if mirrormode && n > 0 {
let _ = guest.socket.send_to(&udp_buffer[..n],&srcaddr);
}
udp_nrecv = n;
sourceaddress = srcaddr.clone();
}
},
@ -419,6 +460,9 @@ fn main() {
Ok(n) => if n == 0 {
println!("<-- disconnect {}: {} (closed by remote endpoint)",host.port,client.address);
} else {
if mirrormode && n > 0 {
let _ = client.stream.write_all(&tcp_buffer[..n]);
}
tcp_nrecv = n;
host.clients.push_back(client);
},
@ -439,6 +483,9 @@ fn main() {
} else if host.privacy == PortPrivacy::Whitelist && !srcaddr.ip().is_loopback() && !allowlist.contains(&srcaddr.ip()) {
println!("-x- refuse {}/udp: {} (not listed in {})",host.port,srcaddr,ALLOWFILE_NAME);
} else {
if mirrormode && n > 0 {
let _ = host.socket.send_to(&udp_buffer[..n],&srcaddr);
}
udp_nrecv = n;
sourceaddress = srcaddr;
let newclient = UdpClient {