Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #16

Merged
merged 3 commits into from
Dec 13, 2021
Merged

Dev #16

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
build-release.sh
build-release.sh
.vscode
77 changes: 77 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ path = "src/server.rs"
name = "fuc"
path = "src/client.rs"


[dependencies]
aes = {version = "0.7.5"}
block-modes = "0.8.1"
hex-literal = "0.3.4"
log = {version = "0.4.14"}
clap = {version = "3.0.0-beta.5", features = ["yaml"]}
smol = {version = "1.2.5"}
Expand Down
107 changes: 79 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ A fast, stable, cross-platform and efficient intranet penetration and port forwa
[![GitHub license](https://img.shields.io/github/license/editso/fuso)](https://github.com/editso/fuso)
[![Downloads](https://img.shields.io/github/downloads/editso/fuso/total?label=Release%20Download)](https://github.com/editso/fuso/releases/latest)

### Fuso make PortForward & IntranetAccess Easy 😁
### Fuso make PortForward & IntranetAccess Easy

👉 这是一款用于内网穿透 端口转发的神器,帮助运维 开发 快速部署与接入内网 同时支持CobaltStrike 一键转发等功能

👉 还在因为工具的参数过多,体积大而烦恼吗? 我们只实现Socks5与端口转发,快捷的接入与转发内网流量且体积小方便实用
👉 这是一款用于内网穿透 端口转发的工具,帮助运维,开发人员快速部署与接入内网

👉 该项目可直接当做库来使用

Expand All @@ -31,30 +29,82 @@ A fast, stable, cross-platform and efficient intranet penetration and port forwa


### 👀如何使用 (How to use) ❓

1. 你需要先[下载](https://github.com/editso/fuso/releases/latest)或[构建](#Build)Fuso

2. 服务端程序为`fus`, 客户端程序为`fuc`

3. 测试
1. 运行`fus`(服务端默认监听`9003`端口) 与 `fuc`(客户端默认转发`80`端口)
2. 确保服务端端口(`9003`)未被使用
3. 确保转发的端口(`80`)有服务在运行
4. 转发成功后需要访问的端口由服务端随机分配
5. 服务端出现 **New mapping xxxx -> xxxx**日志则代表转发服务已准备就绪

4. 配置
`Fuso` 的所有配置都是通过参数传递的方式
打开终端运行 `[fus or fuc] --help` 即可获取帮助信息

5. 高级用法 `>1.0.2`
1. 支持从客户端指定服务端要监听的端口(*前提你所指定的端口没有被占用!*) 用法:
`fuc [--bind or -b] 端口`
2. 支持多连接
3. 级联代理(`桥接模式`), 支持级联代理, 用法:
开启桥模式 `fuc [--bridge ] 端口` **开启后它既支持桥接也支持穿透互不影响**
使用 `fuc 已开启桥接模式的地址 端口` 其它参数基本一致

1. 你需要先[下载](https://github.com/editso/fuso/releases/latest)或[构建](#Build)`Fuso`
2. `fuso` 分为客户端(`fuc`)与服务端(`fus`)
3. 将你下载或构建好的`fus`程序[部署](#服务端部署)到服务器
4. 将你下载或构建好的`fuc`程序[部署](#客户端部署)到你需要穿透的电脑上

#### 服务端部署
1. 采用参数传递的形式来部署无需任何配置文件, 并且配置简单大多情况下可使用默认配置

2. **参数说明**
`-h`: 绑定的地址
`-p`: 监听的端口, 也就是客户端需要连接到服务端的端口
`-x`: `xor`加密的`key` (*目前暂时定义为`xor`加密的`key`, 未来可能因加密方式变化所改动*)
`-l`: 日志信息级别 (`debug`, `info`, `trace`, `error`, `warn`)
`-v`: 该参数打印的版本目前无效
`-h`: 获取帮助信息


#### 客户端部署
客户端配置相对服务端来说可能会复杂一点, 但大多数情况下也可使用默认配置

1 **参数说明**
fuc [options] <server-host> <server-port>

`<server-host>`: 服务端地址, 支持域名
`<server-port>`: 服务端监听的端口
`-h`: 需要转发的地址, 也就是穿透地址
`-p`: 转发的端口, 需要配合 `-h`参数
`-b`: 真实映射成功后访问的端口号, 不指定将自动分配
`-n`: 一个标识, 映射服务的名称
`-w`: 使用`Websocket`进程握手连接
`-x`: `xor`加密的`key` (*目前暂时定义为`xor`加密的`key`, 未来可能因加密方式 变化所改动*)
`-l`: 日志信息级别 (`debug`, `info`, `trace`, `error`, `warn`)
`--bridge-host`: 桥接服务监听的地址
`--bridge-port`: 桥接服务监听的端口

```
# 一个转发例子
# 服务端绑定在 xxx.xxx.xxx.xxx:9003
# 转发内网中 10.10.10.8:80 到 xxx.xxx.xxx.xxx:8080
# 需要注意的是:
# 10.10.10.8 必须是能 ping 通的
# 80 端口必须有服务在运行
# 服务端已经在运行,并且服务端80端口没有被占用

# 运行:
> fuc -h 10.10.10.8 -p 80 -b 8080 xxx.xxx.xxx.xxx 9003

# 该命令运行后既可以是转发模式, 也可以是Socks5模式都可以使用8080端口进行访问


# 一个桥接例子
# 什么时候能用到桥接模式呢?
# 比如:
# 你的内网中只有一台机器可以出网, 但是我想访问不能出网机器上所运行的服务
# 那么此时就可以使用桥接模式, 通过可以在出网的机器上开启桥接模式来转发不能出网的服务
# 前提是你不能出网的机器和可以出网的机器在同一个内网中, 并且可以相互 ping 通

# 在可以出网的机器上开启桥接 (0.0.0.0:9004)
# 假设可以出网的内网ip地址为 10.10.10.5
# 运行:
> fuc -h 10.10.10.8 -p 80 -b 8080 --bridge-host 0.0.0.0 --bridge-port 9004 xxx.xxx.xxx.xxx 9003

# 在不可以出网的机器上需要穿透80服务, 并且服务端监听8081端口
# 此时fuc的服务端地址就不应该是服务器地址, 因为并不能出网, 所有需要连接到开启桥接服务的地址
# 运行:
> fuc -h 127.0.0.1 -p 80 -b 8081 10.10.10.5 9004


# 另一种桥接做法
# 假设不能出网机器的ip地址为 10.10.10.6
# 在可以出网的机器上运行:
> fuc -h 10.10.10.6 -p 80 -b 8081 xxx.xxx.xxx.xxx 9003

# 此时也可以达到效果, 但是这样一来可以出网的就无法转发自己所监听的服务

```

### 🤔Features
| Name | <font color="green">✔(Achieved)</font> / <font color="red">❌(Unrealized)</font>) |
Expand All @@ -67,6 +117,7 @@ A fast, stable, cross-platform and efficient intranet penetration and port forwa
| 多映射 | <font color="green">✔</font> |
| 级联代理 | <font color="green">✔</font> |
| 数据传输压缩 | ❌ |
| Websocket | <font color="green">✔</font> |


### 😶部分功能还待完善敬请期待..
Expand Down
42 changes: 40 additions & 2 deletions fuso-api/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ pub trait FusoPacket {
async fn send(&mut self, packet: Packet) -> Result<()>;
}

#[async_trait]
pub trait FusoStreamEx {
async fn send_opt_data(&mut self, data: Option<Bytes>) -> Result<()>;
}

#[async_trait]
pub trait FusoEncoder<OUT> {
async fn encode(&self) -> Result<OUT>;
Expand Down Expand Up @@ -165,6 +170,7 @@ impl Packet {
let magic = packet.get_u32();

if Self::magic() != magic {
log::warn!("{:?}", String::from_utf8_lossy(&data));
return Err(error::ErrorKind::BadPacket.into());
}

Expand Down Expand Up @@ -204,10 +210,12 @@ impl Packet {
self.cmd
}

#[inline]
pub fn get_data(&self) -> &Bytes {
&self.data
}

#[inline]
pub fn get_mut_data(&mut self) -> &mut Bytes {
&mut self.data
}
Expand Down Expand Up @@ -301,6 +309,22 @@ where
}
}

#[async_trait]
impl<T> FusoStreamEx for T
where
T: AsyncWrite + Unpin + Send + Sync + 'static,
{
#[inline]
async fn send_opt_data(&mut self, mut data: Option<Bytes>) -> Result<()> {
if let Some(data) = data.take() {
log::debug!("[send_opt_data] len={}", data.len());
self.write_all(&data).await.map_err(|e| e.into())
} else {
Ok(())
}
}
}

impl<T, A> Spawn for T
where
A: Send + 'static,
Expand All @@ -309,8 +333,9 @@ where
#[inline]
fn detach(self) {
static GLOBAL: once_cell::sync::Lazy<Executor<'_>> = once_cell::sync::Lazy::new(|| {
for n in 1..num_cpus::get() {
log::trace!("spwan executor thread fuso-{}", n);
println!("cpu {}", num_cpus::get());
for n in 0..num_cpus::get() {
log::trace!("spawn executor thread fuso-{}", n);
std::thread::Builder::new()
.name(format!("fuso-{}", n))
.spawn(|| loop {
Expand Down Expand Up @@ -364,6 +389,19 @@ impl AsyncTcpSocketEx<TcpListener, TcpStream> for SocketAddr {
}
}

#[async_trait]
impl AsyncTcpSocketEx<TcpListener, TcpStream> for String {
#[inline]
async fn tcp_listen(self) -> Result<TcpListener> {
TcpListener::bind(self).await.map_err(|e| e.into())
}

#[inline]
async fn tcp_connect(self) -> Result<TcpStream> {
TcpStream::connect(self).await.map_err(|e| e.into())
}
}

impl<T> RollbackEx<T, Buffer<u8>> for T
where
T: AsyncRead + AsyncWrite + Send + Sync + 'static,
Expand Down
2 changes: 1 addition & 1 deletion fuso-api/src/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl UdpListener {
loop {
let mut buf = Vec::new();

buf.resize(1350, 0);
buf.resize(MTU_BUF_SIZE, 0);

let packet = udp.recv_from(&mut buf).await;

Expand Down
2 changes: 1 addition & 1 deletion fuso-core/src/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub struct Bridge {

impl Bridge {
#[inline]
pub async fn bind(bind_addr: SocketAddr, server_addr: SocketAddr) -> Result<Self> {
pub async fn bind(bind_addr: String, server_addr: SocketAddr) -> Result<Self> {
let listen = bind_addr.tcp_listen().await?;

let (accept_tx, accept_ax) = unbounded();
Expand Down
Loading