mirror of
https://github.com/EFForg/rayhunter.git
synced 2026-07-29 02:08:13 -07:00
fix up ci, build installer in actions
This commit is contained in:
committed by
Cooper Quintin
parent
4a94545498
commit
64a87534ee
@@ -88,6 +88,42 @@ jobs:
|
|||||||
name: rayhunter-daemon-${{ matrix.device.name }}
|
name: rayhunter-daemon-${{ matrix.device.name }}
|
||||||
path: target/armv7-unknown-linux-musleabihf/release/rayhunter-daemon
|
path: target/armv7-unknown-linux-musleabihf/release/rayhunter-daemon
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
build_rust_installer:
|
||||||
|
needs:
|
||||||
|
- build_rayhunter
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
platform:
|
||||||
|
- name: ubuntu-24
|
||||||
|
os: ubuntu-latest
|
||||||
|
target: x86_64-unknown-linux-musl
|
||||||
|
- name: ubuntu-24-aarch64
|
||||||
|
os: ubuntu-24.04-arm
|
||||||
|
target: aarch64-unknown-linux-musl
|
||||||
|
- name: macos-arm
|
||||||
|
os: macos-latest
|
||||||
|
target: aarch64-apple-darwin
|
||||||
|
- name: macos-intel
|
||||||
|
os: macos-13
|
||||||
|
target: x86_64-apple-darwin
|
||||||
|
- name: windows-x86_64
|
||||||
|
os: windows-latest
|
||||||
|
target: x86_64-pc-windows-gnu
|
||||||
|
runs-on: ${{ matrix.platform.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
targets: ${{ matrix.platform.target }}
|
||||||
|
|
||||||
|
- run: cargo build --bin installer --release --target ${{ matrix.platform.target }} --features vendor
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: tplink-installer-${{ matrix.platform.name }}
|
||||||
|
path: target/${{ matrix.platform.target }}/release/installer${{ matrix.platform.os == 'windows-latest' && '.exe' || '' }}
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
build_release_zip:
|
build_release_zip:
|
||||||
needs:
|
needs:
|
||||||
- build_serial_and_check
|
- build_serial_and_check
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ name = "installer"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
vendor = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.98"
|
anyhow = "1.0.98"
|
||||||
clap = { version = "4.5.37", features = ["derive"] }
|
clap = { version = "4.5.37", features = ["derive"] }
|
||||||
|
|||||||
+77
-27
@@ -2,12 +2,12 @@ use std::net::SocketAddr;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use anyhow::{Context, Error};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use anyhow::{Context, Error};
|
|
||||||
use tokio::net::{TcpStream};
|
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
use tokio::net::TcpStream;
|
||||||
use tokio::time::{sleep, timeout};
|
use tokio::time::{sleep, timeout};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
@@ -15,13 +15,12 @@ use tokio::time::{sleep, timeout};
|
|||||||
struct Args {
|
struct Args {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: Command,
|
command: Command,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum Command {
|
enum Command {
|
||||||
/// Install rayhunter on the TP-Link M7350.
|
/// Install rayhunter on the TP-Link M7350.
|
||||||
InstallTplink(InstallTpLink)
|
InstallTplink(InstallTpLink),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
@@ -55,21 +54,26 @@ async fn main() -> Result<(), Error> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn main_tplink(args: InstallTpLink) -> Result<(), Error> {
|
async fn main_tplink(args: InstallTpLink) -> Result<(), Error> {
|
||||||
let InstallTpLink { skip_sdcard, username, password, admin_ip } = args;
|
let InstallTpLink {
|
||||||
|
skip_sdcard,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
admin_ip,
|
||||||
|
} = args;
|
||||||
|
|
||||||
let qcmap_auth_endpoint = format!("http://{admin_ip}/cgi-bin/qcmap_auth");
|
let qcmap_auth_endpoint = format!("http://{admin_ip}/cgi-bin/qcmap_auth");
|
||||||
let qcmap_web_cgi_endpoint = format!("http://{admin_ip}/cgi-bin/qcmap_web_cgi");
|
let qcmap_web_cgi_endpoint = format!("http://{admin_ip}/cgi-bin/qcmap_web_cgi");
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct NonceResponse {
|
struct NonceResponse {
|
||||||
nonce: String
|
nonce: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
|
|
||||||
let NonceResponse { nonce } = client.post(&qcmap_auth_endpoint)
|
let NonceResponse { nonce } = client
|
||||||
|
.post(&qcmap_auth_endpoint)
|
||||||
.body(r#"{"module":"authenticator","action":0}"#)
|
.body(r#"{"module":"authenticator","action":0}"#)
|
||||||
.send()
|
.send()
|
||||||
.await?
|
.await?
|
||||||
@@ -83,10 +87,11 @@ async fn main_tplink(args: InstallTpLink) -> Result<(), Error> {
|
|||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct TokenResponse {
|
struct TokenResponse {
|
||||||
token: String
|
token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
let TokenResponse { token } = client.post(&qcmap_auth_endpoint)
|
let TokenResponse { token } = client
|
||||||
|
.post(&qcmap_auth_endpoint)
|
||||||
.json(&json!({
|
.json(&json!({
|
||||||
"module": "authenticator",
|
"module": "authenticator",
|
||||||
"action": 1,
|
"action": 1,
|
||||||
@@ -102,7 +107,8 @@ async fn main_tplink(args: InstallTpLink) -> Result<(), Error> {
|
|||||||
|
|
||||||
for language in &["$(busybox telnetd -l /bin/sh)", "en"] {
|
for language in &["$(busybox telnetd -l /bin/sh)", "en"] {
|
||||||
println!("Setting language of device to {language}");
|
println!("Setting language of device to {language}");
|
||||||
client.post(&qcmap_web_cgi_endpoint)
|
client
|
||||||
|
.post(&qcmap_web_cgi_endpoint)
|
||||||
.header("Cookie", format!("tpweb_token={token}"))
|
.header("Cookie", format!("tpweb_token={token}"))
|
||||||
.json(&json!({
|
.json(&json!({
|
||||||
"token": token,
|
"token": token,
|
||||||
@@ -110,7 +116,8 @@ async fn main_tplink(args: InstallTpLink) -> Result<(), Error> {
|
|||||||
"action": 1,
|
"action": 1,
|
||||||
"language": language
|
"language": language
|
||||||
}))
|
}))
|
||||||
.send().await?
|
.send()
|
||||||
|
.await?
|
||||||
.error_for_status()?;
|
.error_for_status()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,15 +135,46 @@ async fn main_tplink(args: InstallTpLink) -> Result<(), Error> {
|
|||||||
telnet_send_command(addr, "mkdir -p /data", "exit code 0").await?;
|
telnet_send_command(addr, "mkdir -p /data", "exit code 0").await?;
|
||||||
telnet_send_command(addr, "ln -sf /mnt/card /data/rayhunter", "exit code 0").await?;
|
telnet_send_command(addr, "ln -sf /mnt/card /data/rayhunter", "exit code 0").await?;
|
||||||
|
|
||||||
telnet_send_file(addr, "/mnt/card/config.toml", include_bytes!("../../dist/config.toml.example")).await?;
|
telnet_send_file(
|
||||||
telnet_send_file(addr, "/mnt/card/rayhunter-daemon", include_bytes!("../../dist/rayhunter-daemon-tplink")).await?;
|
addr,
|
||||||
telnet_send_file(addr, "/etc/init.d/rayhunter_daemon", include_bytes!("../../dist/scripts/rayhunter_daemon")).await?;
|
"/mnt/card/config.toml",
|
||||||
|
include_bytes!("../../dist/config.toml.example"),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
telnet_send_command(addr, "chmod ugo+x /mnt/card/rayhunter-daemon", "exit code 0").await?;
|
#[cfg(feature = "vendor")]
|
||||||
telnet_send_command(addr, "chmod 755 /etc/init.d/rayhunter_daemon", "exit code 0").await?;
|
let rayhunter_daemon_bin =
|
||||||
|
include_bytes!("../../rayhunter-daemon-tplink/rayhunter-daemon-tplink");
|
||||||
|
|
||||||
|
#[cfg(not(feature = "vendor"))]
|
||||||
|
let rayhunter_daemon_bin =
|
||||||
|
&tokio::fs::read("target/armv7-unknown-linux-gnueabihf/release/rayhunter-daemon").await?;
|
||||||
|
|
||||||
|
telnet_send_file(addr, "/mnt/card/rayhunter-daemon", rayhunter_daemon_bin).await?;
|
||||||
|
telnet_send_file(
|
||||||
|
addr,
|
||||||
|
"/etc/init.d/rayhunter_daemon",
|
||||||
|
include_bytes!("../../dist/scripts/rayhunter_daemon"),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
telnet_send_command(
|
||||||
|
addr,
|
||||||
|
"chmod ugo+x /mnt/card/rayhunter-daemon",
|
||||||
|
"exit code 0",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
telnet_send_command(
|
||||||
|
addr,
|
||||||
|
"chmod 755 /etc/init.d/rayhunter_daemon",
|
||||||
|
"exit code 0",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
telnet_send_command(addr, "update-rc.d rayhunter_daemon defaults", "exit code 0").await?;
|
telnet_send_command(addr, "update-rc.d rayhunter_daemon defaults", "exit code 0").await?;
|
||||||
|
|
||||||
println!("Done. Rebooting device. After it's started up again, check out the web interface at http://{admin_ip}:8080");
|
println!(
|
||||||
|
"Done. Rebooting device. After it's started up again, check out the web interface at http://{admin_ip}:8080"
|
||||||
|
);
|
||||||
|
|
||||||
telnet_send_command(addr, "reboot", "exit code 0").await?;
|
telnet_send_command(addr, "reboot", "exit code 0").await?;
|
||||||
|
|
||||||
@@ -165,21 +203,30 @@ async fn telnet_send_file(addr: SocketAddr, filename: &str, payload: &[u8]) -> R
|
|||||||
handle.await??;
|
handle.await??;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let checksum = md5::compute(payload);
|
let checksum = md5::compute(payload);
|
||||||
|
|
||||||
telnet_send_command(
|
telnet_send_command(
|
||||||
addr,
|
addr,
|
||||||
&format!("md5sum {filename}.tmp"),
|
&format!("md5sum {filename}.tmp"),
|
||||||
&format!("{checksum:x} {filename}.tmp")
|
&format!("{checksum:x} {filename}.tmp"),
|
||||||
).await?;
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
telnet_send_command(addr, &format!("mv {filename}.tmp {filename}"), "exit code 0").await?;
|
telnet_send_command(
|
||||||
|
addr,
|
||||||
|
&format!("mv {filename}.tmp {filename}"),
|
||||||
|
"exit code 0",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn telnet_send_command(addr: SocketAddr, command: &str, expected_output: &str) -> Result<(), Error> {
|
async fn telnet_send_command(
|
||||||
|
addr: SocketAddr,
|
||||||
|
command: &str,
|
||||||
|
expected_output: &str,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let stream = TcpStream::connect(addr).await?;
|
let stream = TcpStream::connect(addr).await?;
|
||||||
let (mut reader, mut writer) = stream.into_split();
|
let (mut reader, mut writer) = stream.into_split();
|
||||||
|
|
||||||
@@ -187,7 +234,7 @@ async fn telnet_send_command(addr: SocketAddr, command: &str, expected_output: &
|
|||||||
let mut buf = [0];
|
let mut buf = [0];
|
||||||
reader.read(&mut buf).await?;
|
reader.read(&mut buf).await?;
|
||||||
if buf[0] == b'#' {
|
if buf[0] == b'#' {
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +246,9 @@ async fn telnet_send_command(addr: SocketAddr, command: &str, expected_output: &
|
|||||||
let _ = timeout(Duration::from_secs(5), async {
|
let _ = timeout(Duration::from_secs(5), async {
|
||||||
let mut buf = [0; 4096];
|
let mut buf = [0; 4096];
|
||||||
loop {
|
loop {
|
||||||
let Ok(bytes_read) = reader.read(&mut buf).await else { break };
|
let Ok(bytes_read) = reader.read(&mut buf).await else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
let bytes = &buf[..bytes_read];
|
let bytes = &buf[..bytes_read];
|
||||||
if bytes.is_empty() {
|
if bytes.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
@@ -208,10 +257,11 @@ async fn telnet_send_command(addr: SocketAddr, command: &str, expected_output: &
|
|||||||
read_buf.extend(bytes);
|
read_buf.extend(bytes);
|
||||||
|
|
||||||
if read_buf.ends_with(b"/ # ") {
|
if read_buf.ends_with(b"/ # ") {
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).await;
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
let string = String::from_utf8_lossy(&read_buf);
|
let string = String::from_utf8_lossy(&read_buf);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user