sterepando commited on
Commit
92d868e
·
verified ·
1 Parent(s): 1cb3827

Update Dockerfile

Browse files
Files changed (1) hide show
  1. Dockerfile +54 -168
Dockerfile CHANGED
@@ -1,14 +1,10 @@
1
- FROM rust:slim-bullseye
2
 
3
- # 1. Установка системных зависимостей
4
  RUN apt-get update && apt-get install -y \
5
- curl \
6
- unzip \
7
- build-essential \
8
- libssl-dev \
9
- pkg-config \
10
- zip \
11
- python3 \
12
  && rm -rf /var/lib/apt/lists/*
13
 
14
  # 2. Установка Android NDK
@@ -21,172 +17,62 @@ RUN curl -Lo ndk.zip https://dl.google.com/android/repository/android-ndk-r25c-l
21
  ENV ANDROID_NDK_HOME=/opt/android-ndk
22
  ENV PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin
23
 
24
- # 3. Настройка Rust таргетов
25
  RUN rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android
26
  RUN cargo install cargo-ndk
27
 
28
- # 4. Инициализация проекта
29
  WORKDIR /app
30
- RUN cargo init --lib --name vless_core
31
-
32
- # 5. Cargo.toml
33
- RUN cat <<EOF > Cargo.toml
34
- [package]
35
- name = "vless_core"
36
- version = "0.3.0"
37
- edition = "2021"
38
-
39
- [lib]
40
- crate-type = ["cdylib"]
41
-
42
- [dependencies]
43
- tokio = { version = "1", features = ["full"] }
44
- libc = "0.2"
45
- anyhow = "1.0"
46
- log = "0.4"
47
- android_logger = "0.13"
48
- lazy_static = "1.4"
49
- serde = { version = "1.0", features = ["derive"] }
50
- serde_json = "1.0"
51
- EOF
52
-
53
- # 6. Исходный код (SOCKS5 -> VLESS Stub)
54
- RUN cat <<EOF > src/lib.rs
55
- use std::ffi::CStr;
56
- use std::os::raw::{c_char, c_int};
57
- use std::sync::{Arc, Mutex};
58
- use log::{info, error, warn, LevelFilter};
59
- use android_logger::Config;
60
- use tokio::runtime::Runtime;
61
- use tokio::task::JoinHandle;
62
- use serde::Deserialize;
63
- use tokio::net::{TcpListener, TcpStream};
64
- use tokio::io::{AsyncReadExt, AsyncWriteExt};
65
-
66
- lazy_static::lazy_static! {
67
- static ref RUNTIME: Runtime = Runtime::new().unwrap();
68
- static ref VPN_HANDLE: Arc<Mutex<Option<JoinHandle<()>>>> = Arc::new(Mutex::new(None));
69
- static ref SOCKS_PORT: Arc<Mutex<u16>> = Arc::new(Mutex::new(0));
70
- }
71
-
72
- #[no_mangle]
73
- pub extern "C" fn init_logger() {
74
- android_logger::init_once(Config::default().with_max_level(LevelFilter::Info).with_tag("MandreVless"));
75
- info!("Mandre VLESS Core v3.0 (SOCKS5 Mode) Initialized");
76
- }
77
-
78
- #[derive(Deserialize, Debug, Clone)]
79
- struct VlessFullConfig {
80
- uuid: String,
81
- address: String,
82
- port: u16,
83
- security: String,
84
- }
85
-
86
- // Простейший SOCKS5 хендшейк (без аутентификации)
87
- async fn handle_socks5_client(mut client: TcpStream, config: VlessFullConfig) {
88
- // 1. Читаем приветствие (версия, методы)
89
- let mut buf = [0u8; 256];
90
- if client.read(&mut buf).await.is_err() { return; }
91
-
92
- // 2. Отвечаем: Версия 5, Метод 0 (No Auth)
93
- if client.write_all(&[0x05, 0x00]).await.is_err() { return; }
94
-
95
- // 3. Читаем запрос подключения (CMD)
96
- if client.read(&mut buf).await.is_err() { return; }
97
-
98
- // Имитируем успешное подключение к целевому серверу (через VLESS)
99
- // В реальном коде здесь мы парсим адрес назначения из SOCKS запроса
100
- // и открываем VLESS стрим к config.address
101
-
102
- // Отвечаем клиенту: Успех (0x00), тип адреса IPv4, адрес 0.0.0.0, порт 0
103
- if client.write_all(&[0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0]).await.is_err() { return; }
104
-
105
- // 4. Проксирование данных (Client <-> VLESS)
106
- // Для демо подключаемся просто к Google (как будто VLESS работает)
107
- // В реальности: TcpStream::connect((config.address, config.port)) и шифрование
108
- let mut remote = match TcpStream::connect("8.8.8.8:53").await { // Демо-заглушка
109
- Ok(s) => s,
110
- Err(_) => return,
111
- };
112
-
113
- let (mut cr, mut cw) = client.split();
114
- let (mut rr, mut rw) = remote.split();
115
-
116
- let _ = tokio::join!(
117
- tokio::io::copy(&mut cr, &mut rw),
118
- tokio::io::copy(&mut rr, &mut cw)
119
- );
120
- }
121
-
122
- async fn vless_server_worker(cfg: VlessFullConfig) {
123
- // Запускаем локальный SOCKS5 сервер на случайном порту
124
- let listener = match TcpListener::bind("127.0.0.1:0").await {
125
- Ok(l) => l,
126
- Err(e) => { error!("Bind Error: {}", e); return; }
127
- };
128
-
129
- let local_port = listener.local_addr().unwrap().port();
130
- info!("🚀 SOCKS5 Local Server listening on 127.0.0.1:{}", local_port);
131
-
132
- // Сохраняем порт, чтобы Python мог его забрать
133
- *SOCKS_PORT.lock().unwrap() = local_port;
134
-
135
- loop {
136
- match listener.accept().await {
137
- Ok((socket, _)) => {
138
- let c = cfg.clone();
139
- tokio::spawn(handle_socks5_client(socket, c));
140
- }
141
- Err(e) => error!("Accept Error: {}", e),
142
- }
143
- }
144
- }
145
-
146
- #[no_mangle]
147
- pub extern "C" fn start_vless(config_json: *const c_char) -> c_int {
148
- let c_str = unsafe { if config_json.is_null() { return -1; } CStr::from_ptr(config_json) };
149
- let str_slice = match c_str.to_str() { Ok(s) => s, Err(_) => return -2 };
150
-
151
- let config: VlessFullConfig = match serde_json::from_str(str_slice) {
152
- Ok(c) => c,
153
- Err(e) => { error!("JSON: {}", e); return -3; }
154
- };
155
-
156
- let mut handle = VPN_HANDLE.lock().unwrap();
157
- if let Some(h) = handle.take() { h.abort(); }
158
-
159
- *handle = Some(RUNTIME.spawn(vless_server_worker(config)));
160
- return 0; // Success, порт нужно получить отдельной функцией
161
- }
162
-
163
- #[no_mangle]
164
- pub extern "C" fn get_local_port() -> c_int {
165
- // Ждем немного, пока порт присвоится (костыль для демо)
166
- // В проде лучше использовать callback или канал
167
- std::thread::sleep(std::time::Duration::from_millis(100));
168
- *SOCKS_PORT.lock().unwrap() as c_int
169
- }
170
-
171
- #[no_mangle]
172
- pub extern "C" fn stop_vless() -> c_int {
173
- let mut handle = VPN_HANDLE.lock().unwrap();
174
- if let Some(h) = handle.take() {
175
- h.abort();
176
- info!("Service Stopped");
177
- return 0;
178
- }
179
- return 1;
180
- }
181
- EOF
182
-
183
- # 7. Компиляция
184
- RUN cargo ndk -t armeabi-v7a -t arm64-v8a -t x86_64 -o ./jniLibs build --release
185
 
186
  # 8. Упаковка
187
- WORKDIR /app
188
  RUN zip -r vless_libs.zip jniLibs
189
 
190
  # 9. Сервер
191
  EXPOSE 7860
192
- CMD ["/usr/bin/python3", "-m", "http.server", "7860"]
 
1
+ FROM rust:bullseye
2
 
3
+ # 1. Установка зависимостей для кросс-компиляции
4
  RUN apt-get update && apt-get install -y \
5
+ curl unzip git build-essential \
6
+ libssl-dev pkg-config python3 python3-pip \
7
+ clang llvm \
 
 
 
 
8
  && rm -rf /var/lib/apt/lists/*
9
 
10
  # 2. Установка Android NDK
 
17
  ENV ANDROID_NDK_HOME=/opt/android-ndk
18
  ENV PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin
19
 
20
+ # 3. Настройка Rust
21
  RUN rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android
22
  RUN cargo install cargo-ndk
23
 
24
+ # 4. Клонирование Leaf (Rust VPN Core)
25
  WORKDIR /app
26
+ # Используем форк или оригинал leaf, поддерживающий VLESS
27
+ RUN git clone https://github.com/eycorsican/leaf.git .
28
+
29
+ # 5. Патчинг Cargo.toml для сборки динамической библиотеки (.so)
30
+ # Добавляем crate-type = ["cdylib"] если его нет
31
+ RUN sed -i 's/crate-type = \["staticlib"\]/crate-type = ["cdylib"]/g' leaf-mobile/Cargo.toml || echo 'crate-type = ["cdylib"]' >> leaf-mobile/Cargo.toml
32
+
33
+ # 6. Создание C-совместимого API (обертка)
34
+ # Leaf Mobile уже имеет JNI, но нам нужен простой C API для Python (ctypes)
35
+ # Создаем src/lib_c.rs в leaf-mobile
36
+ WORKDIR /app/leaf-mobile
37
+ RUN echo 'use std::os::raw::{c_char, c_int};\n\
38
+ use std::ffi::{CStr, CString};\n\
39
+ \n\
40
+ #[no_mangle]\n\
41
+ pub extern "C" fn leaf_run_auto(config_path: *const c_char) -> c_int {\n\
42
+ let c_str = unsafe { CStr::from_ptr(config_path) };\n\
43
+ let config_str = c_str.to_str().unwrap_or("");\n\
44
+ // Запуск Leaf с конфигом\n\
45
+ // (Упрощенный вызов, в реальности leaf::start)\n\
46
+ match leaf::start(0, config_str.to_string()) {\n\
47
+ Ok(_) => 0,\n\
48
+ Err(_) => 1,\n\
49
+ }\n\
50
+ }\n\
51
+ \n\
52
+ #[no_mangle]\n\
53
+ pub extern "C" fn leaf_stop_auto() -> c_int {\n\
54
+ leaf::stop(0);\n\
55
+ 0\n\
56
+ }\n\
57
+ \n\
58
+ #[no_mangle]\n\
59
+ pub extern "C" fn leaf_reload_auto(config_path: *const c_char) -> c_int {\n\
60
+ let c_str = unsafe { CStr::from_ptr(config_path) };\n\
61
+ let config_str = c_str.to_str().unwrap_or("");\n\
62
+ match leaf::reload(0, config_str.to_string()) {\n\
63
+ Ok(_) => 0,\n\
64
+ Err(_) => 1,\n\
65
+ }\n\
66
+ }\n' >> src/lib.rs
67
+
68
+ # 7. Компиляция Leaf Mobile
69
+ # Мы собираем leaf-mobile, так как он содержит нужные зависимости
70
+ RUN cargo ndk -t armeabi-v7a -t arm64-v8a -t x86_64 -o ./jniLibs build --release --lib
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
  # 8. Упаковка
73
+ WORKDIR /app/leaf-mobile
74
  RUN zip -r vless_libs.zip jniLibs
75
 
76
  # 9. Сервер
77
  EXPOSE 7860
78
+ CMD ["python3", "-m", "http.server", "7860"]