Skip to content

Commit 0ef6724

Browse files
committed
readme fix
1 parent d3f6f76 commit 0ef6724

9 files changed

Lines changed: 116 additions & 97 deletions

File tree

README.md

Lines changed: 34 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,72 @@
1-
[![Release](https://github.com/frkn-dev/pony/actions/workflows/release.yml/badge.svg?branch=main)](https://github.com/frkn-dev/pony/actions/workflows/release.yml) [![Pony Build](https://github.com/frkn-dev/pony/actions/workflows/rust.yml/badge.svg?branch=main)](https://github.com/frkn-dev/pony/actions/workflows/rust.yml)
1+
[![Release](https://github.com/frkn-dev/fcore/actions/workflows/release.yml/badge.svg?branch=main)](https://github.com/frkn-dev/fcore/actions/workflows/release.yml) [![Fc0re Build](https://github.com/frkn-dev/pony/actions/workflows/rust.yml/badge.svg?branch=main)](https://github.com/frkn-dev/fcore/actions/workflows/rust.yml)
22

3-
# Pony - a cluster platform for Xray/Shadowsocks/Hysteria2/Wireguard/MTproto
3+
# Fc0re - a cluster platform for Xray/Shadowsocks/Hysteria2/Wireguard/Amnezia-Wireguard/MTproto
44

5-
Pony is a lightweight control plane and orchestration platform for modern proxy protocols. It simplifies the deployment and unified management of Xray, Shadowsocks, Hysteria2, MTproto and Wireguard servers, providing a single pane of glass for your network infrastructure.
5+
Fc0re is a lightweight control plane and orchestration platform for modern proxy protocols.
6+
It simplifies the deployment and unified management of Xray, Shadowsocks, Hysteria2, MTproto, Wireguard and Amnezia-Wireguard servers,
7+
providing a single pane of glass for your network infrastructure.
68

79
## Architecture
810

911
Contains parts
1012

11-
- agent — manages Xray/Wireguard/Hysteria2 connections/users/metrics
12-
- api — manages cluster of servers, gets API calls and send commands to servers
13-
- auth — handles auth for Hysteri2 cleints
14-
- utils — helper to work/debug Bin messages
13+
- node — manages Xray/Shadowsocks/Hysteria2/Wireguard/Amnezia-Wireguard/MTproto connections/users/metrics
14+
- api — manages cluster of servers, gets API calls and send commands to servers using ZeroMQ PUB/SUB mechanizme
15+
- auth — handles auth for Hysteri2 clients and trial API
1516

1617
### As dependencies the platfrom has
1718

1819
- ZeroMQ — communicating bus
1920
- PostgreSQL — user and node data storage
2021
- Xray Core
2122
- Hysteria2
22-
- MTproto
23+
- Teleproxy (MTProxy)
2324
- Wireguard
25+
- Amnezia Wireguard
2426
- Nginx — reverse proxy
2527

2628
### Features
2729

28-
- Standalone Agent — can run without external dependencies: just WG or/and Xray Core and a config file.
30+
- Standalone Node — can run without external dependencies.
2931
- Automatic Xray Config Parsing — reads xray-config.json to fetch inbounds and settings automatically.
30-
- Low Resource Usage — works perfectly on low-cost 1 CPU ($5 VPS) machines.
31-
- Protocol Support — handles VLESS TCP, VLESS gRPC, VLESS Xhttp, Hysteria2 and Wireguard connections.
32+
- Low Resource Usage — works perfectly on low-cost 1 CPU ($3 VPS) machines.
33+
- Protocol Support — handles VLESS TCP, VLESS gRPC, VLESS Xhttp, Hysteria2, Wireguard and Amnezia Wireguard connections.
3234
- Cluster Management — API manages users and nodes across the entire cluster.
3335
- Node Health Monitoring — API periodically checks the health and status of all connected nodes.
3436
- Metrics System — system and logic metrics are collected in Graphite format and stored in Clickhouse for analytics.
35-
- Trial User Support — supports trial users with daily traffic limitation control.
37+
- Trial User Support — supports trial users.
3638

37-
# Utils — CLI Tool for Working with rkyv Messages and ZeroMQ
39+
## Getting Started
3840

39-
## Overview
41+
### Prerequisites
4042

41-
utils is a command-line utility to generate, verify, and send binary rkyv messages used in the messaging system over ZeroMQ. It helps to easily create valid messages from JSON, serialize them to binary files, and publish them on a ZeroMQ topic.
42-
Usage
43+
- **Rust** (nightly toolchain)
44+
- **PostgreSQL** 17+
45+
- **ZeroMQ** libraries installed on your system
46+
- **Protobuf Compiler** (`protoc`)
4347

44-
Generate binary message from JSON
48+
### Installation & Build
4549

46-
```
47-
cargo run --bin utils gen -i path/to/input.json -o path/to/output.bin
48-
49-
-i — path to the JSON file describing the message
50+
1. **Clone the repository:**
5051

51-
-o — path to save the generated binary file
52-
53-
The JSON must match the Message struct format.
52+
```bash
53+
git clone [https://github.com/frkn-dev/fcore.git](https://github.com/frkn-dev/fcore.git)
54+
cd fcore
5455
```
5556

56-
Send a binary message to ZeroMQ publisher
57+
2. **Build all components:**
5758

59+
```bash
60+
cargo build --release
5861
```
59-
cargo run --bin utils send -t topic -i path/to/message.bin -a tcp://127.0.0.1:3000
60-
61-
-t — topic (channel) to publish on
6262

63-
-i — path to the binary message file
63+
3. **Configuration**
6464

65-
-a — ZeroMQ publisher address
65+
```bash
66+
cp config-node-example.toml config-node.toml
67+
cp config-api-example.toml config-api.toml
6668
```
6769

68-
Combined mode: generate and send in one step
70+
## License
6971

70-
cargo run --bin utils all -i path/to/input.json -b path/to/output.bin -t topic -a tcp://127.0.0.1:3000`
71-
72-
Generates binary from JSON, saves it, and immediately publishes it to the given topic and address.
73-
74-
```
75-
Example JSON for Message
76-
77-
{
78-
"conn_id": "9658b391-01cb-4031-a3f5-6cbdd749bcff",
79-
"action": "Create",
80-
"tag": "Wireguard",
81-
"wg": {
82-
"keys": {
83-
"privkey": "privatekeyhere",
84-
"pubkey": "publickeyhere"
85-
},
86-
"address": {
87-
"ip": "10.10.0.24",
88-
"cidr": 32
89-
}
90-
},
91-
"password": null
92-
}
93-
```
72+
This project is licensed under the MIT License - see the LICENSE file for details.

dev/auth.request

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
3+
requests.post(
4+
'http://127.0.0.1:3005/trial',
5+
headers={
6+
'Content-Type': 'application/json'
7+
},
8+
json={
9+
"email": "2pizza1063@gmail.com"
10+
})

src/bin/api/http/handlers/subscription.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ where
205205
Tag::VlessGrpcReality,
206206
Tag::VlessTcpReality,
207207
Tag::VlessXhttpReality,
208+
Tag::Vmess,
208209
];
209210

210211
let xray_nodes = nodes.clone();

src/bin/auth/config.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use serde::Deserialize;
22
use std::net::Ipv4Addr;
33

4-
use fcore::{ApiAccessConfig, MetricsTxConfig, NodeConfigRaw, Result, Settings};
4+
use fcore::{ApiAccessConfig, Env, MetricsTxConfig, NodeConfigRaw, Result, Settings, Tag};
55

66
#[derive(Clone, Debug, Deserialize)]
77
pub struct ServiceSettings {
@@ -48,6 +48,9 @@ pub struct ServiceConfig {
4848
#[serde(default = "default_cors_origin")]
4949
pub origin: String,
5050
pub updates_endpoint_zmq: String,
51+
52+
pub enabled_envs: Vec<Env>,
53+
pub enabled_protos: Vec<Tag>,
5154
}
5255

5356
#[cfg(feature = "email")]

src/bin/auth/filters.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use fcore::ApiAccessConfig;
1+
use fcore::{ApiAccessConfig, Env, Tag};
22
use warp::Filter;
33

44
#[cfg(feature = "email")]
@@ -16,3 +16,15 @@ pub fn with_api_settings(
1616
) -> impl Filter<Extract = (ApiAccessConfig,), Error = std::convert::Infallible> + Clone {
1717
warp::any().map(move || api.clone())
1818
}
19+
20+
pub fn with_envs(
21+
envs: Vec<Env>,
22+
) -> impl Filter<Extract = (Vec<Env>,), Error = std::convert::Infallible> + Clone {
23+
warp::any().map(move || envs.clone())
24+
}
25+
26+
pub fn with_protos(
27+
protos: Vec<Tag>,
28+
) -> impl Filter<Extract = (Vec<Tag>,), Error = std::convert::Infallible> + Clone {
29+
warp::any().map(move || protos.clone())
30+
}

src/bin/auth/handlers.rs

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use tokio::sync::RwLock;
44
use fcore::{
55
http::{helpers as http, response::Instance},
66
ApiAccessConfig, ConnectionBaseOperations, ConnectionStorageBaseOperations, Connections, Env,
7+
Tag,
78
};
89

910
#[cfg(feature = "email")]
@@ -14,12 +15,36 @@ use super::http::HttpClient;
1415
use super::request;
1516
use super::response;
1617
use super::service::DEFAULT_DAYS;
17-
use super::service::PROTOS;
18+
19+
pub async fn auth_handler<C>(
20+
req: request::Auth,
21+
memory: Arc<RwLock<Connections<C>>>,
22+
) -> Result<impl warp::Reply, warp::Rejection>
23+
where
24+
C: ConnectionBaseOperations + Sync + Send + Clone + 'static + std::fmt::Display,
25+
{
26+
tracing::debug!("Auth req {} {} {}", req.auth, req.addr, req.tx);
27+
let mem = memory.read().await;
28+
if let Some(id) = mem.validate_token(&req.auth) {
29+
Ok(warp::reply::json(&response::Auth {
30+
ok: true,
31+
id: Some(id.to_string()),
32+
}))
33+
} else {
34+
Ok(warp::reply::json(&response::Auth {
35+
ok: false,
36+
id: None,
37+
}))
38+
}
39+
}
1840

1941
pub async fn activate_key_handler(
2042
req: request::ActivateKey,
2143
http: HttpClient,
2244
api: ApiAccessConfig,
45+
46+
envs: Vec<Env>,
47+
protos: Vec<Tag>,
2348
) -> Result<impl warp::Reply, warp::Rejection> {
2449
let key = match validate_key(&http, &api.endpoint, &api.token, &req.code).await {
2550
Ok(k) => k,
@@ -45,7 +70,7 @@ pub async fn activate_key_handler(
4570
Err(e) => return Ok(http::internal_error(&format!("Creation failed: {}", e))),
4671
};
4772

48-
if let Err(e) = setup_connections(&http, &api, &sub.id).await {
73+
if let Err(e) = setup_connections(&http, &api, &sub.id, envs, protos).await {
4974
tracing::error!("{}", e);
5075
return Ok(http::internal_error("Failed to establish connections."));
5176
}
@@ -89,6 +114,8 @@ pub async fn trial_handler(
89114
store: EmailStore,
90115
http: HttpClient,
91116
api: ApiAccessConfig,
117+
envs: Vec<Env>,
118+
protos: Vec<Tag>,
92119
) -> Result<impl warp::Reply, warp::Rejection> {
93120
if store.check_email_hmac(&req.email).await {
94121
return Ok(http::bad_request("Trial already requested"));
@@ -104,7 +131,7 @@ pub async fn trial_handler(
104131
}
105132
};
106133

107-
if let Err(e) = setup_connections(&http, &api, &sub.id).await {
134+
if let Err(e) = setup_connections(&http, &api, &sub.id, envs, protos).await {
108135
tracing::error!("{}", e);
109136
return Ok(http::internal_error(
110137
"Failed to establish trial connections.",
@@ -134,6 +161,8 @@ pub async fn tg_trial_handler(
134161
req: request::TgTrial,
135162
http: HttpClient,
136163
api: ApiAccessConfig,
164+
envs: Vec<Env>,
165+
protos: Vec<Tag>,
137166
) -> Result<impl warp::Reply, warp::Rejection> {
138167
let referred_by = req.referred_by.unwrap_or_else(|| "TG".to_string());
139168

@@ -147,7 +176,7 @@ pub async fn tg_trial_handler(
147176
};
148177

149178
// 2. Create connections
150-
if let Err(e) = setup_connections(&http, &api, &sub.id).await {
179+
if let Err(e) = setup_connections(&http, &api, &sub.id, envs, protos).await {
151180
tracing::error!("{}", e);
152181
return Ok(http::internal_error(
153182
"Failed to establish trial connections.",
@@ -161,36 +190,15 @@ pub async fn tg_trial_handler(
161190
))
162191
}
163192

164-
pub async fn auth_handler<C>(
165-
req: request::Auth,
166-
memory: Arc<RwLock<Connections<C>>>,
167-
) -> Result<impl warp::Reply, warp::Rejection>
168-
where
169-
C: ConnectionBaseOperations + Sync + Send + Clone + 'static + std::fmt::Display,
170-
{
171-
tracing::debug!("Auth req {} {} {}", req.auth, req.addr, req.tx);
172-
let mem = memory.read().await;
173-
if let Some(id) = mem.validate_token(&req.auth) {
174-
Ok(warp::reply::json(&response::Auth {
175-
ok: true,
176-
id: Some(id.to_string()),
177-
}))
178-
} else {
179-
Ok(warp::reply::json(&response::Auth {
180-
ok: false,
181-
id: None,
182-
}))
183-
}
184-
}
185-
186193
async fn setup_connections(
187194
http: &HttpClient,
188195
api: &ApiAccessConfig,
189196
sub_id: &uuid::Uuid,
197+
envs: Vec<Env>,
198+
protos: Vec<Tag>,
190199
) -> Result<(), String> {
191-
let envs = [Env::Production, Env::Dev, Env::Ru, Env::Wl];
192200
let futures = envs.iter().flat_map(|env| {
193-
PROTOS.iter().map(move |proto| {
201+
protos.iter().map(move |proto| {
194202
create_connection(http, env, proto, sub_id, &api.endpoint, &api.token)
195203
})
196204
});

src/bin/auth/helpers.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use serde::Deserialize;
22

33
use fcore::{
44
http::response::{Instance, InstanceWithId, ResponseMessage, SubscriptionResponse},
5-
Code, Env, Error, Key, Result, Subscription,
5+
Code, Env, Error, Key, Result, Subscription, Tag,
66
};
77

88
use super::http::HttpClient;
@@ -170,7 +170,7 @@ pub async fn create_subscription(
170170
pub async fn create_connection(
171171
http: &HttpClient,
172172
env: &Env,
173-
proto: &str,
173+
proto: &Tag,
174174
sub_id: &uuid::Uuid,
175175
api_address: &str,
176176
api_token: &str,
@@ -180,7 +180,7 @@ pub async fn create_connection(
180180
let res = auth_headers(
181181
http.post(format!("{}/connection", api_address))
182182
.json(&serde_json::json!({
183-
"env": env.to_string(),
183+
"env": env,
184184
"proto": proto,
185185
"subscription_id": sub_id
186186
})),

0 commit comments

Comments
 (0)