86 lines
2.6 KiB
Rust
86 lines
2.6 KiB
Rust
use std::{net::SocketAddr, sync::Arc};
|
|
|
|
use anyhow::Context;
|
|
use axum::{Router, routing::any};
|
|
use dotenvy::dotenv;
|
|
use tower_http::compression::CompressionLayer;
|
|
use tracing::{error, info, level_filters::LevelFilter};
|
|
use tracing_subscriber::{EnvFilter, fmt, prelude::*};
|
|
|
|
mod crypto;
|
|
mod proxy;
|
|
|
|
#[derive(Clone)]
|
|
pub struct AppState {
|
|
pub client: reqwest::Client,
|
|
pub target_url: reqwest::Url,
|
|
pub key: String,
|
|
pub iv: String,
|
|
}
|
|
|
|
const DEFAULT_TARGET_URL: &str = "https://cloud.linspirer.com:883";
|
|
const DEFAULT_HOST: &str = "0.0.0.0";
|
|
const DEFAULT_PORT: &str = "8080";
|
|
|
|
#[tokio::main]
|
|
async fn main() -> anyhow::Result<()> {
|
|
// Load environment variables from .env file
|
|
dotenv().ok();
|
|
|
|
// Set up logging
|
|
tracing_subscriber::registry()
|
|
.with(fmt::layer())
|
|
.with(
|
|
EnvFilter::builder()
|
|
.with_default_directive(LevelFilter::INFO.into())
|
|
.from_env_lossy(),
|
|
)
|
|
.init();
|
|
|
|
// Load configuration from environment
|
|
let key = std::env::var("LINSPIRER_KEY").context("LINSPIRER_KEY must be set")?;
|
|
let iv = std::env::var("LINSPIRER_IV").context("LINSPIRER_IV must be set")?;
|
|
let target_url_str = std::env::var("LINSPIRER_TARGET_URL");
|
|
let target_url_str = target_url_str.as_deref().unwrap_or(DEFAULT_TARGET_URL);
|
|
let target_url = reqwest::Url::parse(target_url_str)?;
|
|
|
|
let host_str = std::env::var("LINSPIRER_HOST");
|
|
let host = host_str.as_deref().unwrap_or(DEFAULT_HOST);
|
|
let port_str = std::env::var("LINSPIRER_PORT");
|
|
let port = port_str.as_deref().unwrap_or(DEFAULT_PORT);
|
|
let addr_str = format!("{}:{}", host, port);
|
|
let addr: SocketAddr = addr_str
|
|
.parse()
|
|
.context(format!("Invalid address format: {}", addr_str))?;
|
|
|
|
// Create a reqwest client that ignores SSL certificate verification
|
|
let client = reqwest::Client::builder()
|
|
.gzip(true)
|
|
.deflate(true)
|
|
.danger_accept_invalid_certs(true)
|
|
.build()?;
|
|
|
|
// Create shared state
|
|
let state = Arc::new(AppState {
|
|
client,
|
|
target_url,
|
|
key,
|
|
iv,
|
|
});
|
|
|
|
// Build our application with a single route
|
|
let app = Router::new()
|
|
.route("/{*path}", any(proxy::proxy_handler))
|
|
.layer(CompressionLayer::new().gzip(true))
|
|
.with_state(state);
|
|
|
|
// Run the server
|
|
info!("Proxy started on {} => {}", addr_str, target_url_str);
|
|
let listener = tokio::net::TcpListener::bind(&addr).await?;
|
|
if let Err(e) = axum::serve(listener, app.into_make_service()).await {
|
|
error!("Server error: {}", e);
|
|
}
|
|
|
|
Ok(())
|
|
}
|