Skip to content

Commit 6aef211

Browse files
committed
Add: UDP转发
1 parent 815604c commit 6aef211

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ tcp2ws server -l 8080 -p 22
1313
client:
1414
```
1515
tcp2ws -l 2222 -w ws://server:8080
16+
tcp2ws -l 2222 -w ws://server:8080 -udp server:1234 # UDP forward
1617
```
1718

1819
now, you can use `ssh root@client -p 2222` which should be the same as `ssh root@server`

src/client/mod.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use log::*;
22
use url::Url;
33
use tungstenite::Message;
4-
use tokio::net::TcpListener;
4+
use tokio::net::{TcpListener, UdpSocket};
55
use std::io::{Error, ErrorKind};
66
use futures_util::{StreamExt, SinkExt};
77
use tokio::io::{AsyncReadExt, AsyncWriteExt};
@@ -10,6 +10,7 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt};
1010
struct Properties {
1111
local: String,
1212
ws: String,
13+
udp: String,
1314
}
1415

1516
fn parse_args() -> Option<Properties> {
@@ -40,6 +41,15 @@ fn parse_args() -> Option<Properties> {
4041
};
4142
config.ws = ws;
4243
},
44+
"--udp" | "-udp" | "-u" => {
45+
let udp = match args.next() {
46+
Some(udp) => {
47+
udp
48+
},
49+
_ => "".to_string(),
50+
};
51+
config.udp = udp;
52+
},
4353
_ => {}
4454
}
4555
}
@@ -77,7 +87,38 @@ async fn friendly_bind(local: &str) -> Result<TcpListener, Error> {
7787
}
7888
}
7989

90+
async fn server_udp(config: &Properties) -> Result<(), Error> {
91+
let bind = {
92+
let it = UdpSocket::bind(&config.local).await;
93+
if matches!(it, Ok(_)) { it } else {
94+
UdpSocket::bind(&format!("127.0.0.1:{}", &config.local)).await
95+
}
96+
};
97+
match bind {
98+
Ok(udp) => {
99+
let u = config.udp.clone();
100+
tokio::spawn(async move {
101+
loop {
102+
let mut buf = vec![0u8; 1024];
103+
let (le, who) = udp.recv_from(&mut buf).await.unwrap();
104+
debug!("udp: {le}Bytes from {who:?}");
105+
let c = UdpSocket::bind("0.0.0.0:0").await.unwrap();
106+
c.connect(&u).await.unwrap();
107+
c.send(&buf[..le]).await.unwrap();
108+
let le = c.recv(&mut buf).await.unwrap();
109+
udp.send_to(&buf[..le], who).await.unwrap();
110+
}
111+
});
112+
}
113+
Err(e) => {
114+
error!("{e}");
115+
}
116+
}
117+
Ok(())
118+
}
119+
80120
async fn server(config: &Properties) -> Result<(), Error> {
121+
let _ = server_udp(config).await;
81122
let server = match friendly_bind(&config.local).await {
82123
Ok(it) => it,
83124
Err(e) if e.kind() == ErrorKind::InvalidInput => { // 如果用户只提供了端口号

0 commit comments

Comments
 (0)