Skip to content

Commit

Permalink
change example to bin, and prepare to release v0.3
Browse files Browse the repository at this point in the history
  • Loading branch information
timzaak committed May 23, 2024
1 parent c85b9cd commit 6fc0f70
Show file tree
Hide file tree
Showing 13 changed files with 140 additions and 65 deletions.
10 changes: 4 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,8 @@ jobs:
run: ${{ matrix.settings.build }}

- name: Upload artifact
uses: svenstaro/upload-release-action@v2
uses: actions/upload-artifact@v2
with:
asset_name: mproxy-${{ matrix.settings.target }}
file: release/mproxy
tag: ${{ github.ref }}
repo_token: ${{ secrets.GITHUB_TOKEN
draft: true
name: mproxy-${{ matrix.settings.target }}
path: release/*
if-no-files-found: error
17 changes: 15 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
.PHONY: release-mac-x86_64, release-mac-aarch64, release-linux, release-linux-aarch64

name = mproxy
ctrl_name = mpublish
rust_path = agent
release-mac-x86_64:
mkdir -p release
cd $(rust_path) && cargo build --release --target=x86_64-apple-darwin
strip $(rust_path)/target/x86_64-apple-darwin/release/$(name)
otool -L $(rust_path)/target/x86_64-apple-darwin/release/$(name)
cp $(rust_path)/target/x86_64-apple-darwin/release/mproxy ./release/
cp $(rust_path)/target/x86_64-apple-darwin/release/$(name) ./release/
strip $(rust_path)/target/x86_64-apple-darwin/release/$(ctrl_name)
otool -L $(rust_path)/target/x86_64-apple-darwin/release/$(ctrl_name)
cp $(rust_path)/target/x86_64-apple-darwin/release/$(ctrl_name) ./release/

# brew install wget
release-mac-aarch64:
Expand All @@ -16,18 +20,27 @@ release-mac-aarch64:
strip $(rust_path)/target/aarch64-apple-darwin/release/$(name)
otool -L $(rust_path)/target/aarch64-apple-darwin/release/$(name)
cp $(rust_path)/target/aarch64-apple-darwin/release/$(name) ./release/
strip $(rust_path)/target/aarch64-apple-darwin/release/$(ctrl_name)
otool -L $(rust_path)/target/aarch64-apple-darwin/release/$(ctrl_name)
cp $(rust_path)/target/aarch64-apple-darwin/release/$(ctrl_name) ./release/

release-linux-aarch64:
sudo apt-get install -y build-essential
mkdir release
cd $(rust_path) && cargo build --release --target=aarch64-unknown-linux-gnu
strip $(rust_path)/target/aarch64-unknown-linux-gnu/release/$(name)
cp $(rust_path)/target/aarch64-unknown-linux-gnu/release/$(name) ./release/
cd $(rust_path) && cargo build --release --target=aarch64-unknown-linux-gnu
strip $(rust_path)/target/aarch64-unknown-linux-gnu/release/$(ctrl_name)
cp $(rust_path)/target/aarch64-unknown-linux-gnu/release/$(ctrl_name) ./release/



release-linux:
sudo apt-get install -y build-essential
mkdir release
cd $(rust_path) && cargo build --release --target=x86_64-unknown-linux-gnu
strip $(rust_path)/target/x86_64-unknown-linux-gnu/release/$(name)
cp $(rust_path)/target/x86_64-unknown-linux-gnu/release/$(name) ./release
cp $(rust_path)/target/x86_64-unknown-linux-gnu/release/$(name) ./release
strip $(rust_path)/target/x86_64-unknown-linux-gnu/release/$(ctrl_name)
cp $(rust_path)/target/x86_64-unknown-linux-gnu/release/$(ctrl_name) ./release
23 changes: 20 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,23 @@

相比于VPN,该项目代码可集成到只有 MQTT 交互的设备上,本项目的价值在于参考实现。

## 快速开始
1. 下载bin文件:[release page](./releases), `mproxy` `mpublish`
2. 跑mqtt server, [这里](./tree/master/shell) 有如何快速跑测试 rmqtt 的例子,执行 `run_rmqtt.sh` 即可,生产环境参考 prod 目录下的配置。
3. 编写配置文件:`mproxy.yml`,`mpublish.yml`, 可参考[agent](./tree/master/agent) 目录下的同名文件,两者要和并文件放在同一个目录下。
```sh
# 执行 mproxy
./mproxy
# or run with config
./mproxy mproxy.yml

# 向 mproxy 分发指令
./mpublish ls -ls
# or run with config
./mpublish --config=mpublish.conf ls -ls

```

## 实现原理

在宿主上运行 `mproxy` 命令行可执行程序,通过 MQTT 连接 MQTT Server,并订阅 command 主题消息。
Expand Down Expand Up @@ -38,7 +55,7 @@
}
```
### 配置文件
参考 [config.yml](./agent/config.yml)
参考 [mproxy.yml](./agent/mproxy.yml)[mpublish.yml](./agent/mpublish.yml)

### 开发
Install [Rust 1.70+](https://www.rust-lang.org/),
Expand All @@ -50,11 +67,11 @@ cd shell && ./run_mqtt.sh && cd ../
mprocs

# Check MQTT agent if is OK
cd agent && cargo run --example publish_command.rs
cd agent && cargo run --bin mpublish -- --config=mpublish.yml ls -ls
```
Web [Figma UI](https://www.figma.com/design/iyL4dms3B8AWGZS14FCRuf/RMQTT-EXEC?node-id=0%3A1&t=rnIL1LSWwQIXfZdf-1)
## 限制
目前只支持普通的命令, 不支持 `sudo xxx` 之类命令
目前只支持普通的命令, 不支持 `sudo xxx` 需要额外输入,以及 `ls | grep xx` 使用 pipeline 的指令

### 应用场景举例
1. 执行 `sshx`, 暴露 shell 给远端。
Expand Down
14 changes: 1 addition & 13 deletions agent/Cargo.lock

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

4 changes: 2 additions & 2 deletions agent/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mproxy"
version = "0.2.0"
version = "0.3.0"
edition = "2021"

[dependencies]
Expand All @@ -19,7 +19,7 @@ anyhow = "1"
serde_yml = "0.0.7"
serde = { version = "1.0.202", features = ["derive"] }
serde_json = "1.0"
etcetera = "0.8"
#etcetera = "0.8"

shellish_parse = "2"

Expand Down
4 changes: 0 additions & 4 deletions agent/config.yml

This file was deleted.

6 changes: 0 additions & 6 deletions agent/ctrl_config.yml

This file was deleted.

6 changes: 6 additions & 0 deletions agent/mproxy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
server: 'mqtt://127.0.0.1:1883' # MQTT Server
client_id: test_client #MQTT Client ID
#username: test #MQTT Username
#password: password #MQTT Password
#command_topic: cmd/$client_id #subscribe MQTT topic, listen command message, default value is cmd/$client_id
#response_command_topic: cmd/$client_id/resp #the topic to publish the command result
8 changes: 8 additions & 0 deletions agent/mpublish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
server: 'mqtt://127.0.0.1:1883' # MQTT Server
client_id: test_ctrl #MQTT Client ID
#username: test_ctrl_username #MQTT Username
#password: password #MQTT Password

subscribe_client_id: test_client #MQTT Subscribe Client ID
#publish_command_topic: cmd/$client_id #the topic mpublish to pubish
#response_command_topic: cmd/$client_id/resp #the topic mpublish to subscribe
13 changes: 10 additions & 3 deletions agent/src/main.rs → agent/src/bin/mproxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use tracing_subscriber::EnvFilter;

#[derive(Parser, Debug)]
#[clap(name = mproxy::config::APP_NAME, version = env!("CARGO_PKG_VERSION"))]
#[clap(group(ArgGroup::new("cmds").required(true).args(&["CONFIG"]),))]
#[clap(group(ArgGroup::new("cmds").args(&["CONFIG"]),))]
struct Cli {
#[clap(value_parser, name = "CONFIG")]
pub config_path: Option<PathBuf>,
Expand Down Expand Up @@ -54,9 +54,16 @@ mod test {
fn parse_cli() {
let result = Cli::parse_from([APP_NAME, "config.yaml"]);
println!("{:?}", result);
let result = Cli::parse_from([APP_NAME, "--version"]);
//let result = Cli::parse_from([APP_NAME, "--version"]);
//println!("{:?}", result);
//let result = Cli::parse_from([APP_NAME, "--help"]);
//println!("{:?}", result);

let result = Cli::parse_from([APP_NAME, "--", "config.yaml"]);
println!("{:?}", result);
let result = Cli::parse_from([APP_NAME, "--help"]);

let result = Cli::parse_from([APP_NAME, "--config=config.yaml"]);
println!("{:?}", result);

}
}
50 changes: 40 additions & 10 deletions agent/examples/publish_command.rs → agent/src/bin/mpublish.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,37 @@
use std::env;
use std::io::IsTerminal;
use std::path::PathBuf;
use anyhow::bail;
use clap::Parser;
use rumqttc::v5::{AsyncClient, MqttOptions, Incoming};
use rumqttc::v5::mqttbytes::QoS;
use tracing_subscriber::EnvFilter;
use mproxy::message::{RequestMessage, ResponseMessage};
use mproxy::config::CTRL_APP_NAME;


#[derive(Parser, Debug)]
#[clap(name = CTRL_APP_NAME, version = env!("CARGO_PKG_VERSION"))]
struct Cli {
#[arg(short, long, value_name = "FILE")]
pub config: Option<PathBuf>,
pub command: Vec<String>,
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let args:Vec<String> = env::args().collect();
let command = if args.len() > 1 {
args.iter().skip(1).map(|x|x.to_string()).collect::<Vec<_>>().join(" ")
} else {
"ls -ls".to_string()
};

//let config_path:PathBuf = "./ctrl_config.yml".parse().unwrap();
let config_path:PathBuf = "./config.prod.yml".parse().unwrap();
let cli = Cli::parse();
if cli.command.is_empty() {
bail!("no command could be sent to MQTT");
}
let command = cli.command.join(" ");

let is_terminal = std::io::stdout().is_terminal();

tracing_subscriber::fmt().with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::from("debug")),)
.with_ansi(is_terminal).init();

let config = mproxy::config::CtrlConfig::new(config_path).unwrap();
let config = mproxy::config::CtrlConfig::new(cli.config).unwrap();

let mqtt_url = format!("{}?client_id={}", &config.server, &config.client_id);
let mut options = MqttOptions::parse_url(&mqtt_url).unwrap();
Expand Down Expand Up @@ -62,4 +70,26 @@ async fn main() -> anyhow::Result<()> {
tokio::signal::ctrl_c().await?;

Ok(())
}

#[cfg(test)]
mod test{

use clap::Parser;
use crate::Cli;

const APP_NAME:&str = mproxy::config::CTRL_APP_NAME;
#[test]
fn test_cli_01() {

let config = Cli::parse_from([APP_NAME,"--config=config", "ls", "pwd"]);
println!("{config:?}");

let config = Cli::parse_from([APP_NAME, "-c","config.yaml", "ls", "pwd"]);
println!("{config:?}");

let config = Cli::parse_from([APP_NAME, "-c","config.yaml"]);
println!("{config:?}");

}
}
46 changes: 32 additions & 14 deletions agent/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use anyhow::bail;
use etcetera::BaseStrategy;
use std::env;
use anyhow::{bail, Context};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use tracing::info;
Expand All @@ -18,7 +18,11 @@ pub struct Config {

impl Config {
pub fn new(config_path: Option<PathBuf>) -> anyhow::Result<Self> {
let config_path = config_path.unwrap_or_else(|| Self::get_default_config_path());
let config_path = if let Some(config_path)= config_path {
config_path
} else {
Self::get_default_config_path()?
};
if !config_path.is_file() {
bail!("config file not found: {:?}", config_path);
}
Expand All @@ -28,17 +32,12 @@ impl Config {
Ok(config)
}

fn get_default_config_path() -> PathBuf {
let path = etcetera::choose_base_strategy()
.unwrap()
.config_dir()
.join(APP_NAME);
if !path.exists() {
std::fs::create_dir_all(&path).unwrap();
}
path
fn get_default_config_path() -> anyhow::Result<PathBuf> {
let path = get_exec_path()?;
Ok(path.join(format!("{APP_NAME}.yml")))
}


pub fn get_command_topic(&self) -> String {
self.command_topic.clone().unwrap_or_else(||format!("cmd/{}", self.client_id))

Expand All @@ -48,6 +47,8 @@ impl Config {
}
}

pub const CTRL_APP_NAME: &str = "mpublish";


#[derive(Serialize, Deserialize, Debug)]
pub struct CtrlConfig {
Expand All @@ -60,16 +61,26 @@ pub struct CtrlConfig {
subscribe_command_topic: Option<String>,
}
impl CtrlConfig {
pub fn new(config_path:PathBuf) -> anyhow::Result<Self> {
pub fn new(config_path:Option<PathBuf>) -> anyhow::Result<Self> {
let config_path = if let Some(config_path)= config_path {
config_path
} else {
Self::get_default_config_path()?
};
if !config_path.is_file() {
bail!("config file not found: {:?}", config_path);
}
info!("load config from {:?}", config_path);
info!("load ctrl config from {:?}", config_path);
let config = std::fs::read_to_string(config_path)?;
let config: Self = serde_yml::from_str(&config)?;
Ok(config)
}

fn get_default_config_path() -> anyhow::Result<PathBuf> {
let path = get_exec_path()?;
Ok(path.join(format!("{CTRL_APP_NAME}.yml")))
}

pub fn get_publish_command_topic(&self) -> String {
self.publish_command_topic.clone().unwrap_or_else(||format!("cmd/{}", self.subscribe_client_id))

Expand All @@ -81,6 +92,13 @@ impl CtrlConfig {



fn get_exec_path() -> anyhow::Result<PathBuf>{
let path = env::current_exe().with_context(||"can not get exe path")?;
if let Some(path) = path.parent() {
return Ok(path.to_path_buf())
}
bail!("can not get current exe path");
}

#[cfg(test)]
mod test {
Expand Down
Loading

0 comments on commit 6fc0f70

Please sign in to comment.