added mirror mode
This commit is contained in:
parent
58bca50c2c
commit
07b1e0eff1
|
@ -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
|
||||
|
|
61
sunbeam.rs
61
sunbeam.rs
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue