Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e75a4dda25 | ||
|
|
65bfe5c03c | ||
|
|
b7c3e1f80b | ||
|
|
3fb01ce735 | ||
|
|
f14562b26b | ||
|
|
d4f35909c5 | ||
|
|
1ee2b1ff56 | ||
|
|
cab6e8a20f | ||
|
|
e53f8e1c94 | ||
|
|
23819fcb44 | ||
|
|
51930c855f | ||
|
|
690a6f4feb | ||
|
|
56e4020969 | ||
|
|
e06a9a40a3 | ||
|
|
767d2859f9 | ||
|
|
fa0a273865 | ||
|
|
030a7b8784 | ||
|
|
d2cd54d831 | ||
|
|
9c90f6b5cd | ||
|
|
d1e2f549a7 | ||
|
|
ffa9e1ad97 |
@@ -27,7 +27,7 @@ If you want to contribute to [xfrpc](https://github.com/liudf0716/xfrpc), please
|
||||
6. Commit and push your changes, then make a pull request from Github.
|
||||
|
||||
git commit --signoff
|
||||
git push -f
|
||||
git push
|
||||
|
||||
7. Awaiting review, if accepted, merged!
|
||||
|
||||
|
||||
42
README.md
42
README.md
@@ -18,6 +18,9 @@ the following table is detail compatible feature:
|
||||
| tcpmux | Yes | Yes |
|
||||
| http | Yes | Yes |
|
||||
| https | Yes | Yes |
|
||||
| subdomain | No | Yes |
|
||||
| use_encryption | No | Yes |
|
||||
| use_compression | No | Yes |
|
||||
| udp | No | Yes |
|
||||
| p2p | No | Yes |
|
||||
| xtcp | No | Yes |
|
||||
@@ -76,7 +79,7 @@ sequenceDiagram
|
||||
|
||||
```
|
||||
|
||||
## Compile
|
||||
## Compile on Ubuntu 20.04.3 LTS
|
||||
|
||||
xfrp need [libevent](https://github.com/libevent/libevent) [openssl-dev](https://github.com/openssl/openssl) and [json-c](https://github.com/json-c/json-c) support
|
||||
|
||||
@@ -97,6 +100,14 @@ cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
## Compile on OpenWrt
|
||||
|
||||
xfrpc was recruited by openwrt community since version 1.04.515
|
||||
|
||||
anyway I highly recommend you to use latest version
|
||||
|
||||
in order to compile xfrpc in openwrt sdk environment, you should firstly `make menuconfig`, then select `Network --> Web Servers/Proxies ---> xfrpc`
|
||||
|
||||
## Quick start
|
||||
|
||||
**before using xfrpc, you should get frps server: [frps](https://github.com/fatedier/frp/releases)**
|
||||
@@ -132,7 +143,17 @@ local_port = 22
|
||||
remote_port = 6128
|
||||
```
|
||||
|
||||
+ xfrpc http
|
||||
+ xfrpc http&https
|
||||
|
||||
compare with supporting tcp, supporting http&https need to add vhost_http_port&vhost_https_port in frps.ini as the following
|
||||
|
||||
```
|
||||
# frps.ini
|
||||
[common]
|
||||
bind_port = 7000
|
||||
vhost_http_port = 80
|
||||
vhost_https_port = 443
|
||||
```
|
||||
|
||||
```
|
||||
# xfrpc_mini.ini
|
||||
@@ -140,10 +161,15 @@ remote_port = 6128
|
||||
server_addr = x.x.x.x
|
||||
server_port = 7000
|
||||
|
||||
[web]
|
||||
[http]
|
||||
type = http
|
||||
local_port = 80
|
||||
custom_domains = www.example.com
|
||||
|
||||
[https]
|
||||
type = https
|
||||
local_port = 443
|
||||
custom_domains = www.example.com
|
||||
```
|
||||
|
||||
+ Run in debug mode
|
||||
@@ -158,6 +184,12 @@ xfrpc -c frpc_mini.ini -f -d 7
|
||||
xfrpc -c frpc_mini.ini -d 0
|
||||
```
|
||||
|
||||
## Openwrt luci configure ui
|
||||
|
||||
If running xfrpc in openwrt box, [luci-app-xfrpc](https://github.com/liudf0716/luci-app-xfrpc) is a good choice
|
||||
|
||||
luci-app-xfrpc was recruited by [luci project](https://github.com/openwrt/luci)
|
||||
|
||||
## How to contribute our project
|
||||
|
||||
See [CONTRIBUTING](https://github.com/liudf0716/xfrpc/blob/master/CONTRIBUTING.md) for details on submitting patches and the contribution workflow.
|
||||
@@ -184,8 +216,12 @@ QQ群 : [331230369](https://jq.qq.com/?_wv=1027&k=47QGEhL)
|
||||

|
||||
|
||||
|
||||
<!--
|
||||
|
||||
## 广告
|
||||
|
||||
想学习OpenWrt开发,但是摸不着门道?自学没毅力?基础太差?怕太难学不会?跟着佐大学OpenWrt开发入门培训班助你能学有所成
|
||||
|
||||
报名地址:https://forgotfun.org/2018/04/openwrt-training-2018.html
|
||||
|
||||
-->
|
||||
|
||||
2
client.c
2
client.c
@@ -209,7 +209,7 @@ new_proxy_client()
|
||||
struct proxy_client *client = calloc(1, sizeof(struct proxy_client));
|
||||
assert(client);
|
||||
client->stream_id = get_next_session_id();
|
||||
client->send_window = 128*1024;
|
||||
client->send_window = 200*1024;
|
||||
client->stream_state = INIT;
|
||||
HASH_ADD_INT(all_pc, stream_id, client);
|
||||
|
||||
|
||||
2
config.c
2
config.c
@@ -363,7 +363,7 @@ static void init_common_conf(struct common_conf *config)
|
||||
assert(config->log_level);
|
||||
config->log_max_days = 3;
|
||||
config->heartbeat_interval = 30;
|
||||
config->heartbeat_timeout = 60;
|
||||
config->heartbeat_timeout = 90;
|
||||
config->tcp_mux = 1;
|
||||
config->user = NULL;
|
||||
config->server_ip = NULL;
|
||||
|
||||
78
control.c
78
control.c
@@ -35,6 +35,7 @@
|
||||
#include <json-c/json.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "client.h"
|
||||
@@ -53,10 +54,13 @@
|
||||
static struct control *main_ctl;
|
||||
static int clients_conn_signel = 0;
|
||||
static int is_login = 0;
|
||||
static time_t pong_time = 0;
|
||||
|
||||
static void sync_new_work_connection(struct bufferevent *bev, uint32_t sid);
|
||||
static void recv_cb(struct bufferevent *bev, void *ctx);
|
||||
static void clear_main_control();
|
||||
static void start_base_connect();
|
||||
static void keep_control_alive();
|
||||
|
||||
static int
|
||||
is_client_connected()
|
||||
@@ -179,8 +183,7 @@ ping()
|
||||
static void
|
||||
sync_new_work_connection(struct bufferevent *bev, uint32_t sid)
|
||||
{
|
||||
struct bufferevent *bout = bev;
|
||||
assert(bout);
|
||||
assert(bev);
|
||||
|
||||
/* send new work session regist request to frps*/
|
||||
struct work_conn *work_c = new_work_conn();
|
||||
@@ -230,32 +233,25 @@ set_ticker_ping_timer(struct event *timeout)
|
||||
event_add(timeout, &tv);
|
||||
}
|
||||
|
||||
static void
|
||||
set_tcp_mux_ping_timer(struct event *timeout)
|
||||
{
|
||||
struct timeval tv;
|
||||
evutil_timerclear(&tv);
|
||||
tv.tv_sec = 60;
|
||||
event_add(timeout, &tv);
|
||||
}
|
||||
|
||||
static void
|
||||
hb_sender_cb(evutil_socket_t fd, short event, void *arg)
|
||||
{
|
||||
debug(LOG_DEBUG, "hb_sender_cb");
|
||||
if (is_client_connected()) {
|
||||
debug(LOG_DEBUG, "ping frps");
|
||||
ping(NULL);
|
||||
}
|
||||
|
||||
set_ticker_ping_timer(main_ctl->ticker_ping);
|
||||
}
|
||||
|
||||
static void
|
||||
tcp_mux_hb_sender_cb(evutil_socket_t fd, short event, void *arg)
|
||||
{
|
||||
tcp_mux_send_ping(main_ctl->connect_bev, main_ctl->tcp_mux_ping_id++);
|
||||
set_tcp_mux_ping_timer(main_ctl->tcp_mux_ping_event);
|
||||
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
time_t current_time = time(NULL);
|
||||
int interval = current_time - pong_time;
|
||||
if (pong_time && interval > c_conf->heartbeat_timeout) {
|
||||
debug(LOG_INFO, " interval [%d] greater than heartbeat_timeout [%d]", interval, c_conf->heartbeat_timeout);
|
||||
clear_main_control();
|
||||
run_control();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// return: 0: raw succeed 1: raw failed
|
||||
@@ -327,7 +323,7 @@ handle_enc_msg(const uint8_t *enc_msg, int ilen, uint8_t **out)
|
||||
uint8_t *dec_msg = NULL;
|
||||
size_t len = decrypt_data(buf, ilen, get_main_decoder(), &dec_msg);
|
||||
*out = dec_msg;
|
||||
debug(LOG_DEBUG, "dec out len %d ", len);
|
||||
//debug(LOG_DEBUG, "dec out len %d ", len);
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -356,7 +352,7 @@ handle_control_work(const uint8_t *buf, int len, void *ctx)
|
||||
debug(LOG_DEBUG, "cmd_type is %c data is %s", cmd_type, msg->data);
|
||||
switch(cmd_type) {
|
||||
case TypeReqWorkConn:
|
||||
debug(LOG_DEBUG, "TypeReqWorkConn cmd");
|
||||
//debug(LOG_DEBUG, "TypeReqWorkConn cmd");
|
||||
if (! is_client_connected()) {
|
||||
start_proxy_services();
|
||||
client_connected(1);
|
||||
@@ -364,7 +360,7 @@ handle_control_work(const uint8_t *buf, int len, void *ctx)
|
||||
new_client_connect();
|
||||
break;
|
||||
case TypeNewProxyResp:
|
||||
debug(LOG_DEBUG, "TypeNewProxyResp cmd");
|
||||
debug(LOG_DEBUG, "TypeNewProxyResp cmd ");
|
||||
struct new_proxy_response *npr = new_proxy_resp_unmarshal((const char *)msg->data);
|
||||
if (npr == NULL) {
|
||||
debug(LOG_ERR, "new proxy response buffer unmarshal faild!");
|
||||
@@ -411,6 +407,8 @@ handle_control_work(const uint8_t *buf, int len, void *ctx)
|
||||
|
||||
break;
|
||||
case TypePong:
|
||||
//debug(LOG_DEBUG, "receive pong from frps");
|
||||
pong_time = time(NULL);
|
||||
break;
|
||||
default:
|
||||
debug(LOG_INFO, "command type dont support: ctx is %d", ctx?1:0);
|
||||
@@ -512,50 +510,40 @@ connect_event_cb (struct bufferevent *bev, short what, void *ctx)
|
||||
static int retry_times = 1;
|
||||
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
|
||||
if (retry_times >= 100) {
|
||||
debug(LOG_ERR,
|
||||
"have retry connect to xfrp server for %d times, exit!",
|
||||
debug(LOG_INFO,
|
||||
"have retry connect to xfrp server for %d times, exit?",
|
||||
retry_times);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
sleep(retry_times);
|
||||
sleep(2);
|
||||
retry_times++;
|
||||
debug(LOG_ERR, "error: connect server [%s:%d] failed %s",
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port,
|
||||
strerror(errno));
|
||||
clear_main_control();
|
||||
start_base_connect();
|
||||
run_control();
|
||||
} else if (what & BEV_EVENT_CONNECTED) {
|
||||
retry_times = 0;
|
||||
|
||||
tcp_mux_send_win_update_syn(bev, main_ctl->stream_id);
|
||||
login();
|
||||
|
||||
keep_control_alive();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
keep_control_alive()
|
||||
{
|
||||
debug(LOG_DEBUG, "start keep_control_alive");
|
||||
main_ctl->ticker_ping = evtimer_new(main_ctl->connect_base, hb_sender_cb, NULL);
|
||||
if ( !main_ctl->ticker_ping) {
|
||||
debug(LOG_ERR, "Ping Ticker init failed!");
|
||||
return;
|
||||
}
|
||||
pong_time = time(NULL);
|
||||
set_ticker_ping_timer(main_ctl->ticker_ping);
|
||||
}
|
||||
|
||||
static void
|
||||
keep_control_tcp_mux_alive()
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
if (!c_conf->tcp_mux) return;
|
||||
|
||||
main_ctl->tcp_mux_ping_event = evtimer_new(main_ctl->connect_base, tcp_mux_hb_sender_cb, NULL);
|
||||
assert(main_ctl->tcp_mux_ping_event);
|
||||
set_tcp_mux_ping_timer(main_ctl->tcp_mux_ping_event);
|
||||
}
|
||||
|
||||
static void
|
||||
server_dns_cb(int event_code, struct evutil_addrinfo *addr, void *ctx)
|
||||
{
|
||||
@@ -582,7 +570,7 @@ server_dns_cb(int event_code, struct evutil_addrinfo *addr, void *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
start_base_connect()
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
@@ -686,7 +674,7 @@ send_enc_msg_frp_server(struct bufferevent *bev,
|
||||
uint8_t *enc_msg = NULL;
|
||||
size_t olen = encrypt_data((uint8_t *)req_msg, msg_len+sizeof(struct msg_hdr), get_main_encoder(), &enc_msg);
|
||||
assert(olen > 0);
|
||||
debug(LOG_DEBUG, "encrypt_data length %d", olen);
|
||||
//debug(LOG_DEBUG, "encrypt_data length %d", olen);
|
||||
|
||||
tcp_mux_send_data(bout, sid, olen);
|
||||
|
||||
@@ -825,6 +813,10 @@ clear_main_control()
|
||||
if (main_ctl->ticker_ping) evtimer_del(main_ctl->ticker_ping);
|
||||
if (main_ctl->tcp_mux_ping_event) evtimer_del(main_ctl->tcp_mux_ping_event);
|
||||
clear_all_proxy_client();
|
||||
free_evp_cipher_ctx();
|
||||
client_connected(0);
|
||||
pong_time = 0;
|
||||
is_login = 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -843,8 +835,6 @@ void
|
||||
run_control()
|
||||
{
|
||||
start_base_connect();
|
||||
keep_control_alive();
|
||||
keep_control_tcp_mux_alive();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -49,8 +49,6 @@ struct control {
|
||||
|
||||
void connect_eventcb(struct bufferevent *bev, short events, void *ptr);
|
||||
|
||||
void start_base_connect();
|
||||
|
||||
void init_main_control();
|
||||
|
||||
void run_control();
|
||||
|
||||
58
crypto.c
58
crypto.c
@@ -43,6 +43,46 @@ static const char *default_salt = "frp";
|
||||
static const size_t block_size = 16;
|
||||
static struct frp_coder *main_encoder = NULL;
|
||||
static struct frp_coder *main_decoder = NULL;
|
||||
static EVP_CIPHER_CTX *enc_ctx = NULL;
|
||||
static EVP_CIPHER_CTX *dec_ctx = NULL;
|
||||
|
||||
static void
|
||||
free_frp_coder(struct frp_coder *coder)
|
||||
{
|
||||
free(coder->salt);
|
||||
free(coder->privilege_token);
|
||||
free(coder);
|
||||
}
|
||||
|
||||
static void
|
||||
free_all_frp_coder()
|
||||
{
|
||||
if (main_encoder) {
|
||||
free_frp_coder(main_encoder);
|
||||
main_encoder = NULL;
|
||||
}
|
||||
|
||||
if (main_decoder) {
|
||||
free_frp_coder(main_decoder);
|
||||
main_decoder = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
free_evp_cipher_ctx()
|
||||
{
|
||||
free_all_frp_coder();
|
||||
|
||||
if (enc_ctx) {
|
||||
EVP_CIPHER_CTX_free(enc_ctx);
|
||||
enc_ctx = NULL;
|
||||
}
|
||||
|
||||
if (dec_ctx) {
|
||||
EVP_CIPHER_CTX_free(dec_ctx);
|
||||
dec_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
get_block_size()
|
||||
@@ -56,7 +96,7 @@ new_coder(const char *privilege_token, const char *salt)
|
||||
struct frp_coder *enc = calloc(sizeof(struct frp_coder), 1);
|
||||
assert(enc);
|
||||
|
||||
enc->privilege_token = privilege_token ? strdup(privilege_token):"\0";
|
||||
enc->privilege_token = privilege_token ? strdup(privilege_token):strdup("\0");
|
||||
enc->salt = strdup(salt);
|
||||
encrypt_key(enc->privilege_token, strlen(enc->privilege_token), enc->salt, enc->key, block_size);
|
||||
encrypt_iv(enc->iv, block_size);
|
||||
@@ -175,11 +215,11 @@ encrypt_data(const uint8_t *src_data, size_t srclen, struct frp_coder *encoder,
|
||||
assert(outbuf);
|
||||
*ret = outbuf;
|
||||
|
||||
static EVP_CIPHER_CTX *ctx = NULL;
|
||||
if (!ctx) {
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
EVP_EncryptInit_ex(ctx, EVP_aes_128_cfb(), NULL, c->key, c->iv);
|
||||
if (!enc_ctx) {
|
||||
enc_ctx = EVP_CIPHER_CTX_new();
|
||||
EVP_EncryptInit_ex(enc_ctx, EVP_aes_128_cfb(), NULL, c->key, c->iv);
|
||||
}
|
||||
EVP_CIPHER_CTX *ctx = enc_ctx;
|
||||
|
||||
if(!EVP_EncryptUpdate(ctx, outbuf, &tmplen, intext, (int)srclen)) {
|
||||
debug(LOG_ERR, "EVP_EncryptUpdate error!");
|
||||
@@ -208,12 +248,12 @@ decrypt_data(const uint8_t *enc_data, size_t enclen, struct frp_coder *decoder,
|
||||
assert(decoder);
|
||||
|
||||
int outlen = 0, tmplen = 0;
|
||||
static EVP_CIPHER_CTX *ctx= NULL;
|
||||
if (!ctx) {
|
||||
ctx= EVP_CIPHER_CTX_new();
|
||||
EVP_DecryptInit_ex(ctx, EVP_aes_128_cfb(), NULL, c->key, c->iv);
|
||||
if (!dec_ctx) {
|
||||
dec_ctx= EVP_CIPHER_CTX_new();
|
||||
EVP_DecryptInit_ex(dec_ctx, EVP_aes_128_cfb(), NULL, c->key, c->iv);
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX *ctx = dec_ctx;
|
||||
if(!EVP_DecryptUpdate(ctx, outbuf, &tmplen, inbuf, enclen)) {
|
||||
debug(LOG_ERR, "EVP_DecryptUpdate error!");
|
||||
goto D_END;
|
||||
|
||||
1
crypto.h
1
crypto.h
@@ -55,5 +55,6 @@ struct frp_coder *get_main_encoder();
|
||||
struct frp_coder *get_main_decoder();
|
||||
size_t get_block_size();
|
||||
void free_encoder(struct frp_coder *encoder);
|
||||
void free_evp_cipher_ctx();
|
||||
|
||||
#endif // _CRYPTO_H_
|
||||
|
||||
3
msg.c
3
msg.c
@@ -268,8 +268,7 @@ new_proxy_resp_unmarshal(const char *jres)
|
||||
if (port) {
|
||||
port++;
|
||||
npr->remote_port = atoi(port);
|
||||
}else
|
||||
goto END_ERROR;
|
||||
}
|
||||
|
||||
struct json_object *npr_proxy_name = NULL;
|
||||
if (! json_object_object_get_ex(j_np_res, "proxy_name", &npr_proxy_name))
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2022 Dengfeng Liu
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=xfrpc
|
||||
PKG_VERSION:=master
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/liudf0716/xfrpc.git
|
||||
PKG_SOURCE_VERSION:=$(PKG_VERSION)
|
||||
PKG_MIRROR_HASH:=a7141da8a85203d8341fd6d2551f1228396ae54aace6ec0bad2dfeb89e0a377d
|
||||
|
||||
PKG_MAINTAINER:=Dengfeng Liu <liudf0716@gmail.com>
|
||||
PKG_LICENSE:=GPL-3.0-or-later
|
||||
PKG_LICENSE_FILES:=COPYING
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/xfrpc
|
||||
SUBMENU:=Web Servers/Proxies
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
DEPENDS:=+zlib +libjson-c +libevent2 +libevent2-openssl
|
||||
TITLE:= C language fast reverse proxy client
|
||||
URL:=https://github.com/liudf0716/xfrpc
|
||||
endef
|
||||
|
||||
define Package/xfrpc/description
|
||||
xfrpc is C language fast reverse proxy client
|
||||
compare with golang version frpc
|
||||
xfrpc can run in almost all openwrt device
|
||||
endef
|
||||
|
||||
define Package/xfrpc/conffiles
|
||||
/etc/config/xfrpc
|
||||
endef
|
||||
|
||||
define Package/xfrpc/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/xfrpc $(1)/usr/bin/xfrpc
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/xfrpc.init $(1)/etc/init.d/xfrpc
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(CP) ./files/xfrpc.conf $(1)/etc/config/xfrpc
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,xfrpc))
|
||||
@@ -1,26 +0,0 @@
|
||||
config xfrp 'init'
|
||||
option disabled 1
|
||||
option loglevel 7
|
||||
|
||||
config xfrpc 'common'
|
||||
option server_addr 127.0.0.1
|
||||
option server_port 7000
|
||||
option token abdesf13d
|
||||
|
||||
config xfrpc 'ssh01'
|
||||
option type tcp
|
||||
option local_ip 127.0.0.1
|
||||
option local_port 22
|
||||
option remote_port 6000
|
||||
|
||||
#config xfrpc 'web01'
|
||||
# option type http
|
||||
# option local_ip 127.0.0.1
|
||||
# option local_port 8080
|
||||
# option custom_domains yourdomain
|
||||
|
||||
#config xfrpc 'web02'
|
||||
# option type https
|
||||
# option local_ip 127.0.0.1
|
||||
# option local_port 8443
|
||||
# option custom_domains yourdomain
|
||||
@@ -1,93 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2022 Dengfeng Liu <liu_df@qq.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
START=99
|
||||
USE_PROCD=1
|
||||
|
||||
NAME=xfrpc
|
||||
PROG=/usr/bin/$NAME
|
||||
|
||||
|
||||
handle_xfrpc() {
|
||||
local name="$1"
|
||||
local config="$2"
|
||||
|
||||
echo "[$name]" >> "$config"
|
||||
|
||||
handle_type() {
|
||||
uci_validate_section xfrpc xfrpc "$name" \
|
||||
'type:or("tcp", "udp", "ftp", "http", "https")' \
|
||||
'local_ip:ipaddr:127.0.0.1' \
|
||||
'local_port:uinteger'
|
||||
|
||||
echo "type = $type" >> "$config"
|
||||
echo "local_ip = $local_ip" >> "$config"
|
||||
echo "local_port = $local_port" >> "$config"
|
||||
case "$type" in
|
||||
"tcp"|"udp")
|
||||
config_get remote_port "$name" remote_port
|
||||
echo "remote_port = $remote_port" >> "$config"
|
||||
;;
|
||||
"ftp")
|
||||
config_get remote_port "$name" remote_port
|
||||
config_get remote_data_port "$name" remote_data_port
|
||||
echo "remote_port = $remote_port" >> "$config"
|
||||
echo "remote_data_port = $remote_data_port" >> "$config"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
if [ "$name" = "common" ]; then
|
||||
uci_validate_section xfrpc xfrpc "$name" \
|
||||
'server_addr:ipaddr' \
|
||||
'server_port:uinteger' \
|
||||
'token:string'
|
||||
|
||||
[ -z "$token" ] && {
|
||||
echo "no token"
|
||||
exit
|
||||
}
|
||||
echo "server_addr = $server_addr" >> "$config"
|
||||
echo "server_port = $server_port" >> "$config"
|
||||
echo "token = $token" >> "$config"
|
||||
else
|
||||
handle_type
|
||||
fi
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "$NAME"
|
||||
}
|
||||
|
||||
start_service() {
|
||||
local conf_file="/var/etc/$NAME.ini"
|
||||
|
||||
> "$conf_file"
|
||||
config_load "$NAME"
|
||||
|
||||
uci_validate_section xfrpc xfrpc init \
|
||||
'disabled:bool:1' \
|
||||
'loglevel:uinteger:0'
|
||||
|
||||
if [ $disabled = 1 ]; then
|
||||
echo "xfrpc service disabled"
|
||||
return
|
||||
fi
|
||||
|
||||
config_foreach handle_xfrpc xfrpc "$conf_file"
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG" -c "$conf_file" -f -d $loglevel
|
||||
procd_set_param file "$conf_file"
|
||||
procd_set_param respawn
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
26
tcpmux.c
26
tcpmux.c
@@ -70,6 +70,16 @@ flag_2_desc(enum tcp_mux_flag flag)
|
||||
return "unkown_flag";
|
||||
}
|
||||
|
||||
static int
|
||||
valid_tcp_mux_flag(uint16_t flag)
|
||||
{
|
||||
for(int i = 0; i < sizeof(flag_desc)/sizeof(struct tcp_mux_flag_desc); i++){
|
||||
if (flag == flag_desc[i].flag)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
valid_tcp_mux_type(uint8_t type)
|
||||
{
|
||||
@@ -131,7 +141,8 @@ parse_tcp_mux_proto(uint8_t *data, int len, uint32_t *flag, uint32_t *type, uint
|
||||
|
||||
struct tcp_mux_header *hdr = (struct tcp_mux_header *)data;
|
||||
if(hdr->version == proto_version &&
|
||||
valid_tcp_mux_type(hdr->type)) {
|
||||
valid_tcp_mux_type(hdr->type) &&
|
||||
valid_tcp_mux_flag(htons(hdr->flags))) {
|
||||
if (hdr->type == DATA && !valid_tcp_mux_sid(htonl(hdr->stream_id))) {
|
||||
debug(LOG_INFO, "!!!!!type is DATA but cant find stream_id : type [%s] flag [%s] stream_id[%d]",
|
||||
type_2_desc(hdr->type), flag_2_desc(htons(hdr->flags)), htonl(hdr->stream_id));
|
||||
@@ -235,10 +246,17 @@ handle_tcp_mux_frps_msg(uint8_t *buf, int ilen, void (*fn)(uint8_t *, int, void
|
||||
static uint32_t l_dlen = 0;
|
||||
static uint32_t l_type = 0;
|
||||
static uint32_t l_flag = 0;
|
||||
static int8_t only_data = 0;
|
||||
uint8_t *data = buf;
|
||||
while (ilen > 0) {
|
||||
uint32_t type = 0, stream_id = 0, dlen = 0, flag = 0;
|
||||
uint32_t is_tmux = parse_tcp_mux_proto(data, ilen, &flag, &type, &stream_id, &dlen);
|
||||
uint32_t is_tmux;
|
||||
if (only_data) {
|
||||
is_tmux = 0;
|
||||
only_data = 0;
|
||||
} else {
|
||||
is_tmux = parse_tcp_mux_proto(data, ilen, &flag, &type, &stream_id, &dlen);
|
||||
}
|
||||
if (!is_tmux) {
|
||||
struct proxy_client *pc = get_proxy_client(l_stream_id);
|
||||
debug(LOG_DEBUG, "receive only %s data : l_stream_id %d l_type %s l_flag %s l_dlen %d ilen %d",
|
||||
@@ -295,8 +313,10 @@ handle_tcp_mux_frps_msg(uint8_t *buf, int ilen, void (*fn)(uint8_t *, int, void
|
||||
switch(type) {
|
||||
case DATA:
|
||||
{
|
||||
if (ilen == 0)
|
||||
if (ilen == 0) {
|
||||
only_data = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pc || (pc && !pc->local_proxy_bev)) {
|
||||
assert(ilen >= dlen);
|
||||
|
||||
Reference in New Issue
Block a user