Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3fb01ce735 | ||
|
|
f14562b26b | ||
|
|
d4f35909c5 | ||
|
|
1ee2b1ff56 | ||
|
|
cab6e8a20f | ||
|
|
e53f8e1c94 | ||
|
|
23819fcb44 | ||
|
|
51930c855f | ||
|
|
690a6f4feb | ||
|
|
56e4020969 | ||
|
|
e06a9a40a3 | ||
|
|
767d2859f9 | ||
|
|
fa0a273865 | ||
|
|
030a7b8784 | ||
|
|
d2cd54d831 | ||
|
|
9c90f6b5cd | ||
|
|
d1e2f549a7 | ||
|
|
ffa9e1ad97 | ||
|
|
ca64905266 | ||
|
|
6b1f70407c | ||
|
|
5d298156e4 | ||
|
|
37f124ffe7 | ||
|
|
675e47ef43 | ||
|
|
176e4006f6 | ||
|
|
d91d5d91ef | ||
|
|
36eba09bbe | ||
|
|
4ac16540b7 | ||
|
|
ab4da37e72 | ||
|
|
b49dd4e97c | ||
|
|
6fb2e167d6 | ||
|
|
4b633a7c2a |
@@ -31,12 +31,12 @@ set(src_xfrpc
|
||||
crypto.c
|
||||
fastpbkdf2.c
|
||||
utils.c
|
||||
session.c
|
||||
common.c
|
||||
login.c
|
||||
proxy_tcp.c
|
||||
proxy_ftp.c
|
||||
proxy.c
|
||||
tcpmux.c
|
||||
)
|
||||
|
||||
set(libs
|
||||
|
||||
@@ -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!
|
||||
|
||||
|
||||
67
README.md
67
README.md
@@ -3,22 +3,24 @@
|
||||
|
||||
## What is xfrpc
|
||||
|
||||
`xfrpc` is [frp](https://github.com/fatedier/frp) client implemented by c language for [OpenWRT](https://github.com/openwrt/openwrt) and [LEDE](https://github.com/lede-project/source) system
|
||||
|
||||
The motivation to start xfrpc project is that we are OpenWRTer, and openwrt usually ran in device which has little ROM and RAM space, however golang always need more space and memory; therefore we start xfrpc project to support frp.
|
||||
`xfrpc` is [frp](https://github.com/fatedier/frp) client implemented by c language for [OpenWRT](https://github.com/openwrt/openwrt)
|
||||
The motivation to start xfrpc project is that we are OpenWRTer, and openwrt usually run in devices which have limit ROM and RAM space, however frpc always need more space and memory; therefore we launched xfrpc project.
|
||||
|
||||
## Development Status
|
||||
|
||||
xfrpc partially compitable with latest frp release feature, It target to fully compatible with latest frp release.
|
||||
xfrpc partially compitable with latest frp release feature, It targets to fully compatible with latest frp release.
|
||||
|
||||
the following table is detail compatible feature:
|
||||
|
||||
| Feature | xfrpc | frpc |
|
||||
| ------------- | ------------- | ---------|
|
||||
| tcp | Yes | Yes |
|
||||
| tcpmux | No | Yes |
|
||||
| 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 |
|
||||
@@ -77,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
|
||||
|
||||
@@ -98,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)**
|
||||
@@ -110,11 +120,8 @@ frps use latest release 0.42.0
|
||||
# frps.ini
|
||||
[common]
|
||||
bind_port = 7000
|
||||
tcp_mux = false
|
||||
```
|
||||
|
||||
**attention! cause xfrpc does not support tcp_mux yet, please disable tcp_mux otherwise xfrpc can not connect frps**
|
||||
|
||||
run frps
|
||||
|
||||
```
|
||||
@@ -136,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
|
||||
@@ -144,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
|
||||
@@ -162,6 +184,10 @@ xfrpc -c frpc_mini.ini -f -d 7
|
||||
xfrpc -c frpc_mini.ini -d 0
|
||||
```
|
||||
|
||||
## Openwrt UI
|
||||
|
||||
If running xfrpc in openwrt box, [luci-app-xfrpc](https://github.com/liudf0716/luci-app-xfrpc) is a good choice
|
||||
|
||||
## 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.
|
||||
@@ -173,8 +199,27 @@ QQ群 : [331230369](https://jq.qq.com/?_wv=1027&k=47QGEhL)
|
||||
|
||||
## Please support us and star our project
|
||||
|
||||
[](https://star-history.com/#liudf0716/xfrpc&Date)
|
||||
|
||||
## 打赏
|
||||
|
||||
支付宝打赏
|
||||
|
||||

|
||||
|
||||
|
||||
微信打赏
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
<!--
|
||||
|
||||
## 广告
|
||||
|
||||
想学习OpenWrt开发,但是摸不着门道?自学没毅力?基础太差?怕太难学不会?跟着佐大学OpenWrt开发入门培训班助你能学有所成
|
||||
|
||||
报名地址:https://forgotfun.org/2018/04/openwrt-training-2018.html
|
||||
|
||||
-->
|
||||
|
||||
86
client.c
86
client.c
@@ -29,20 +29,12 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/util.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "client.h"
|
||||
@@ -55,15 +47,16 @@
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
#include "utils.h"
|
||||
#include "tcpmux.h"
|
||||
|
||||
static struct proxy_client *all_pc = NULL;
|
||||
|
||||
static void
|
||||
xfrp_worker_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
{
|
||||
struct proxy_client *client = (struct proxy_client *)ctx;
|
||||
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
|
||||
debug(LOG_DEBUG, "working connection closed!");
|
||||
bufferevent_free(bev);
|
||||
free_proxy_client(client);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,9 +67,14 @@ xfrp_proxy_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
assert(client);
|
||||
|
||||
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
|
||||
debug(LOG_DEBUG, "xfrpc proxy close connect server [%s:%d] : %s", client->ps->local_ip, client->ps->local_port, strerror(errno));
|
||||
bufferevent_free(bev);
|
||||
} else if (what & BEV_EVENT_CONNECTED) {
|
||||
debug(LOG_DEBUG, "xfrpc proxy close connect server [%s:%d] stream_id %d: %s",
|
||||
client->ps->local_ip, client->ps->local_port,
|
||||
client->stream_id, strerror(errno));
|
||||
tcp_mux_send_win_update_fin(client->ctl_bev, client->stream_id);
|
||||
client->stream_state = LOCAL_CLOSE;
|
||||
} else if (what & BEV_EVENT_CONNECTED) {
|
||||
debug(LOG_DEBUG, "client [%d] connected", client->stream_id);
|
||||
//client->stream_state = ESTABLISHED;
|
||||
if (client->data_tail_size > 0) {
|
||||
debug(LOG_DEBUG, "send client data ...");
|
||||
send_client_data_tail(client);
|
||||
@@ -127,7 +125,7 @@ start_xfrp_tunnel(struct proxy_client *client)
|
||||
client->local_proxy_bev = connect_server(base, ps->local_ip, ps->local_port);
|
||||
if ( !client->local_proxy_bev ) {
|
||||
debug(LOG_ERR, "frpc tunnel connect local proxy port [%d] failed!", ps->local_port);
|
||||
bufferevent_free(client->ctl_bev);
|
||||
del_proxy_client(client);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -137,30 +135,30 @@ start_xfrp_tunnel(struct proxy_client *client)
|
||||
ps->local_ip ? ps->local_ip:"::1",
|
||||
ps->local_port);
|
||||
|
||||
bufferevent_data_cb proxy_s2c_cb, proxy_c2s_cb;
|
||||
bufferevent_data_cb proxy_s2c_recv, proxy_c2s_recv;
|
||||
if (is_ftp_proxy(client->ps)) {
|
||||
proxy_c2s_cb = ftp_proxy_c2s_cb;
|
||||
proxy_s2c_cb = ftp_proxy_s2c_cb;
|
||||
//ctl_prox->remote_data_port = client->ps->remote_data_port;
|
||||
//ctl_prox->proxy_name = strdup(ps->proxy_name);
|
||||
proxy_c2s_recv = ftp_proxy_c2s_cb;
|
||||
proxy_s2c_recv = ftp_proxy_s2c_cb;
|
||||
} else {
|
||||
proxy_c2s_cb = tcp_proxy_c2s_cb; // local service <---> xfrpc
|
||||
proxy_s2c_cb = tcp_proxy_s2c_cb; // frps <---> xfrpc
|
||||
proxy_c2s_recv = tcp_proxy_c2s_cb; // local service ---> xfrpc
|
||||
proxy_s2c_recv = tcp_proxy_s2c_cb; // frps ---> xfrpc
|
||||
}
|
||||
|
||||
bufferevent_setcb(client->ctl_bev,
|
||||
proxy_s2c_cb,
|
||||
|
||||
if (!c_conf->tcp_mux) {
|
||||
bufferevent_setcb(client->ctl_bev,
|
||||
proxy_s2c_recv,
|
||||
NULL,
|
||||
xfrp_worker_event_cb,
|
||||
client);
|
||||
bufferevent_enable(client->ctl_bev, EV_READ|EV_WRITE);
|
||||
}
|
||||
|
||||
bufferevent_setcb(client->local_proxy_bev,
|
||||
proxy_c2s_cb,
|
||||
proxy_c2s_recv,
|
||||
NULL,
|
||||
xfrp_proxy_event_cb,
|
||||
client);
|
||||
|
||||
bufferevent_enable(client->ctl_bev, EV_READ|EV_WRITE);
|
||||
bufferevent_enable(client->local_proxy_bev, EV_READ|EV_WRITE);
|
||||
}
|
||||
|
||||
@@ -177,19 +175,18 @@ send_client_data_tail(struct proxy_client *client)
|
||||
return send_l;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
free_proxy_client(struct proxy_client *client)
|
||||
{
|
||||
if (client->ev_timeout) evtimer_del(client->ev_timeout);
|
||||
if (client->local_proxy_bev) bufferevent_free(client->local_proxy_bev);
|
||||
free(client);
|
||||
}
|
||||
|
||||
void
|
||||
del_proxy_client(struct proxy_client *client)
|
||||
{
|
||||
struct proxy_client *all_pc = get_all_pc();
|
||||
if (!client || !all_pc ) {
|
||||
debug(LOG_INFO, "Error: all_pc or client is NULL");
|
||||
debug(LOG_INFO, "all_pc or client is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -198,14 +195,12 @@ del_proxy_client(struct proxy_client *client)
|
||||
free_proxy_client(client);
|
||||
}
|
||||
|
||||
// Return NULL if proxy service not found with proxy_name
|
||||
struct proxy_service *
|
||||
get_proxy_service(const char *proxy_name)
|
||||
struct proxy_client *
|
||||
get_proxy_client(uint32_t sid)
|
||||
{
|
||||
struct proxy_service *ps = NULL;
|
||||
struct proxy_service *all_ps = get_all_proxy_services();
|
||||
HASH_FIND_STR(all_ps, proxy_name, ps);
|
||||
return ps;
|
||||
struct proxy_client *pc = NULL;
|
||||
HASH_FIND_INT(all_pc, &sid, pc);
|
||||
return pc;
|
||||
}
|
||||
|
||||
struct proxy_client *
|
||||
@@ -213,5 +208,22 @@ 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 = 200*1024;
|
||||
client->stream_state = INIT;
|
||||
HASH_ADD_INT(all_pc, stream_id, client);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
void
|
||||
clear_all_proxy_client()
|
||||
{
|
||||
if (!all_pc) return;
|
||||
|
||||
struct proxy_client *client, *tmp;
|
||||
HASH_ITER(hh, all_pc, client, tmp) {
|
||||
HASH_DEL(all_pc, client);
|
||||
free_proxy_client(client);
|
||||
}
|
||||
}
|
||||
|
||||
24
client.h
24
client.h
@@ -20,7 +20,7 @@
|
||||
\********************************************************************/
|
||||
|
||||
/** @file client.h
|
||||
@brief xfrp client proxy client related
|
||||
@brief xfrpc proxy client related
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
#include "tcpmux.h"
|
||||
|
||||
struct event_base;
|
||||
struct base_conf;
|
||||
@@ -42,17 +43,19 @@ struct proxy_client {
|
||||
struct event_base *base;
|
||||
struct bufferevent *ctl_bev; // xfrpc proxy <---> frps
|
||||
struct bufferevent *local_proxy_bev; // xfrpc proxy <---> local service
|
||||
struct event *ev_timeout;
|
||||
|
||||
struct base_conf *bconf;
|
||||
|
||||
//private arguments
|
||||
UT_hash_handle hh;
|
||||
|
||||
uint32_t stream_id;
|
||||
uint32_t send_window;
|
||||
enum tcp_mux_state stream_state;
|
||||
int connected;
|
||||
int work_started;
|
||||
struct proxy_service *ps;
|
||||
unsigned char *data_tail; // storage untreated data
|
||||
size_t data_tail_size;
|
||||
|
||||
// private arguments
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
struct proxy_service {
|
||||
@@ -75,7 +78,7 @@ struct proxy_service {
|
||||
char *http_user;
|
||||
char *http_pwd;
|
||||
|
||||
//provate arguments
|
||||
// private arguments
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
@@ -88,13 +91,14 @@ void start_xfrp_tunnel(struct proxy_client *client);
|
||||
|
||||
void del_proxy_client(struct proxy_client *client);
|
||||
|
||||
void free_proxy_client(struct proxy_client *client);
|
||||
|
||||
struct proxy_service *get_proxy_service(const char *proxy_name);
|
||||
struct proxy_client *get_proxy_client(uint32_t sid);
|
||||
|
||||
int send_client_data_tail(struct proxy_client *client);
|
||||
|
||||
int is_ftp_proxy(const struct proxy_service *ps);
|
||||
|
||||
struct proxy_client *new_proxy_client();
|
||||
|
||||
void clear_all_proxy_client();
|
||||
|
||||
#endif //_CLIENT_H_
|
||||
|
||||
@@ -110,7 +110,7 @@ get_daemon_status()
|
||||
/** @internal
|
||||
* @brief Print usage
|
||||
*
|
||||
* Prints usage, called when wifidog is run with -h or with an unknown option
|
||||
* Prints usage, called when xfrpc is run with -h or with an unknown option
|
||||
*/
|
||||
static void
|
||||
usage(const char *appname)
|
||||
|
||||
26
common.c
26
common.c
@@ -1,3 +1,29 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file common.c
|
||||
@brief xfrp common function implemented
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
36
common.h
36
common.h
@@ -1,3 +1,29 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file common.h
|
||||
@brief xfrp common header
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_H_
|
||||
#define _COMMON_H_
|
||||
|
||||
@@ -6,6 +32,16 @@
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/util.h>
|
||||
#include <event2/event.h>
|
||||
#include <event2/dns.h>
|
||||
#include <event2/event_struct.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "uthash.h"
|
||||
|
||||
#define BIGENDIAN_64BIT 1
|
||||
|
||||
50
config.c
50
config.c
@@ -20,7 +20,7 @@
|
||||
\********************************************************************/
|
||||
|
||||
/** @file config.c
|
||||
@brief xfrp client config related
|
||||
@brief xfrpc client config related
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
#include <stdio.h>
|
||||
@@ -42,8 +42,7 @@
|
||||
#include "version.h"
|
||||
|
||||
static struct common_conf *c_conf;
|
||||
static struct proxy_client *p_clients;
|
||||
static struct proxy_service *p_services;
|
||||
static struct proxy_service *all_ps;
|
||||
|
||||
static void new_ftp_data_proxy_service(struct proxy_service *ftp_ps);
|
||||
|
||||
@@ -84,16 +83,6 @@ void free_base_config(struct base_conf *bconf)
|
||||
if (bconf->subdomain) free(bconf->subdomain);
|
||||
}
|
||||
|
||||
struct proxy_client *get_all_pc()
|
||||
{
|
||||
return p_clients;
|
||||
}
|
||||
|
||||
struct proxy_service *get_all_proxy_services()
|
||||
{
|
||||
return p_services;
|
||||
}
|
||||
|
||||
static int is_true(const char *val)
|
||||
{
|
||||
if (val && (strcmp(val, "true") == 0 || strcmp(val, "1") == 0))
|
||||
@@ -110,9 +99,7 @@ static const char *get_valid_type(const char *val)
|
||||
#define MATCH_VALUE(s) strcmp(val, s) == 0
|
||||
if (MATCH_VALUE("tcp") ||
|
||||
MATCH_VALUE("http") ||
|
||||
MATCH_VALUE("https") ||
|
||||
MATCH_VALUE("udp") ||
|
||||
MATCH_VALUE("ftp")) {
|
||||
MATCH_VALUE("https")) {
|
||||
|
||||
return val;
|
||||
}
|
||||
@@ -161,7 +148,7 @@ static void dump_all_ps()
|
||||
struct proxy_service *ps = NULL, *tmp = NULL;
|
||||
|
||||
int index = 0;
|
||||
HASH_ITER(hh, p_services, ps, tmp) {
|
||||
HASH_ITER(hh, all_ps, ps, tmp) {
|
||||
dump_proxy_service(index++, ps);
|
||||
}
|
||||
}
|
||||
@@ -203,7 +190,7 @@ static void new_ftp_data_proxy_service(struct proxy_service *ftp_ps)
|
||||
struct proxy_service *ps = NULL;
|
||||
char *ftp_data_proxy_name = get_ftp_data_proxy_name((const char *)ftp_ps->proxy_name);
|
||||
|
||||
HASH_FIND_STR(p_services, ftp_data_proxy_name, ps);
|
||||
HASH_FIND_STR(all_ps, ftp_data_proxy_name, ps);
|
||||
if (!ps) {
|
||||
ps = new_proxy_service(ftp_data_proxy_name);
|
||||
if (! ps) {
|
||||
@@ -220,7 +207,7 @@ static void new_ftp_data_proxy_service(struct proxy_service *ftp_ps)
|
||||
ps->local_ip = ftp_ps->local_ip;
|
||||
ps->local_port = 0; //will be init in working tunnel connectting
|
||||
|
||||
HASH_ADD_KEYPTR(hh, p_services, ps->proxy_name, strlen(ps->proxy_name), ps);
|
||||
HASH_ADD_KEYPTR(hh, all_ps, ps->proxy_name, strlen(ps->proxy_name), ps);
|
||||
}
|
||||
|
||||
free(ftp_data_proxy_name);
|
||||
@@ -240,7 +227,7 @@ proxy_service_handler(void *user, const char *sect, const char *nm, const char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_FIND_STR(p_services, section, ps);
|
||||
HASH_FIND_STR(all_ps, section, ps);
|
||||
if (!ps) {
|
||||
ps = new_proxy_service(section);
|
||||
if (! ps) {
|
||||
@@ -248,7 +235,7 @@ proxy_service_handler(void *user, const char *sect, const char *nm, const char *
|
||||
exit(0);
|
||||
}
|
||||
|
||||
HASH_ADD_KEYPTR(hh, p_services, ps->proxy_name, strlen(ps->proxy_name), ps);
|
||||
HASH_ADD_KEYPTR(hh, all_ps, ps->proxy_name, strlen(ps->proxy_name), ps);
|
||||
}
|
||||
|
||||
#define MATCH_NAME(s) strcmp(nm, s) == 0
|
||||
@@ -354,7 +341,8 @@ static int common_handler(void *user, const char *section, const char *name, con
|
||||
config->user = strdup(value);
|
||||
assert(config->user);
|
||||
} else if (MATCH("common", "tcp_mux")) {
|
||||
config->tcp_mux = 0; // set tcp_mux to default: false
|
||||
config->tcp_mux = atoi(value);
|
||||
config->tcp_mux = !!config->tcp_mux;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -375,8 +363,8 @@ 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->tcp_mux = 0;
|
||||
config->heartbeat_timeout = 90;
|
||||
config->tcp_mux = 1;
|
||||
config->user = NULL;
|
||||
config->server_ip = NULL;
|
||||
config->is_router = 0;
|
||||
@@ -435,3 +423,17 @@ int is_running_in_router()
|
||||
{
|
||||
return c_conf->is_router;
|
||||
}
|
||||
|
||||
struct proxy_service *
|
||||
get_proxy_service(const char *proxy_name)
|
||||
{
|
||||
struct proxy_service *ps = NULL;
|
||||
HASH_FIND_STR(all_ps, proxy_name, ps);
|
||||
return ps;
|
||||
}
|
||||
|
||||
struct proxy_service *
|
||||
get_all_proxy_services()
|
||||
{
|
||||
return all_ps;
|
||||
}
|
||||
|
||||
20
config.h
20
config.h
@@ -20,7 +20,7 @@
|
||||
\********************************************************************/
|
||||
|
||||
/** @file config.h
|
||||
@brief xfrp client config related
|
||||
@brief xfrpc client config related
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
#ifndef _CONFIG_H_
|
||||
@@ -34,11 +34,11 @@
|
||||
struct base_conf{
|
||||
char *name;
|
||||
char *auth_token;
|
||||
int use_encryption;
|
||||
int use_gzip;
|
||||
int privilege_mode;
|
||||
int use_encryption;
|
||||
int use_gzip;
|
||||
int privilege_mode;
|
||||
char *privilege_token;
|
||||
int pool_count;
|
||||
int pool_count;
|
||||
char *host_header_rewrite;
|
||||
char *subdomain;
|
||||
};
|
||||
@@ -65,17 +65,21 @@ struct common_conf {
|
||||
};
|
||||
|
||||
struct common_conf *get_common_config();
|
||||
struct proxy_service *get_all_proxy_services();
|
||||
|
||||
void free_common_config();
|
||||
|
||||
void free_base_config(struct base_conf *bconf);
|
||||
|
||||
struct proxy_client *get_all_pc();
|
||||
|
||||
void load_config(const char *confile);
|
||||
|
||||
char *get_ftp_data_proxy_name(const char *ftp_proxy_name);
|
||||
|
||||
void set_common_server_ip(const char *ip);
|
||||
|
||||
int is_running_in_router();
|
||||
|
||||
struct proxy_service *get_proxy_service(const char *proxy_name);
|
||||
|
||||
struct proxy_service *get_all_proxy_services();
|
||||
|
||||
#endif //_CONFIG_H_
|
||||
|
||||
12
const.h
12
const.h
@@ -20,7 +20,7 @@
|
||||
\********************************************************************/
|
||||
|
||||
/** @file const.h
|
||||
@brief xfrp constant parameter define
|
||||
@brief xfrpc constant parameter define
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
@@ -34,15 +34,5 @@ enum server_status {
|
||||
Closed
|
||||
};
|
||||
|
||||
// msg type
|
||||
// enum msg_type {
|
||||
// NewCtlConn = 0,
|
||||
// NewWorkConn,
|
||||
// NoticeUserConn,
|
||||
// NewCtlConnRes,
|
||||
// HeartbeatReq,
|
||||
// HeartbeatRes,
|
||||
// NewWorkConnUdp
|
||||
// };
|
||||
|
||||
#endif
|
||||
|
||||
276
control.c
276
control.c
@@ -34,14 +34,8 @@
|
||||
#include <netinet/in.h>
|
||||
#include <json-c/json.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/util.h>
|
||||
#include <event2/event.h>
|
||||
#include <event2/dns.h>
|
||||
#include <event2/event_struct.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "client.h"
|
||||
@@ -53,16 +47,20 @@
|
||||
#include "uthash.h"
|
||||
#include "crypto.h"
|
||||
#include "utils.h"
|
||||
#include "session.h"
|
||||
#include "common.h"
|
||||
#include "login.h"
|
||||
#include "tcpmux.h"
|
||||
|
||||
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);
|
||||
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()
|
||||
@@ -108,11 +106,11 @@ client_start_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
}
|
||||
debug(LOG_ERR, "Proxy connect server [%s:%d] error: %s", c_conf->server_addr, c_conf->server_port, strerror(errno));
|
||||
bufferevent_free(bev);
|
||||
free_proxy_client(client);
|
||||
del_proxy_client(client);
|
||||
} else if (what & BEV_EVENT_CONNECTED) {
|
||||
bufferevent_setcb(bev, recv_cb, NULL, client_start_event_cb, client);
|
||||
bufferevent_enable(bev, EV_READ|EV_WRITE);
|
||||
sync_new_work_connection(bev);
|
||||
sync_new_work_connection(bev, 0);
|
||||
client_connected(1);
|
||||
debug(LOG_INFO, "proxy service start");
|
||||
}
|
||||
@@ -125,6 +123,14 @@ new_client_connect()
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
assert(c_conf);
|
||||
client->base = main_ctl->connect_base;
|
||||
|
||||
if (c_conf->tcp_mux) {
|
||||
debug(LOG_DEBUG, "new client through tcp mux: %d", client->stream_id);
|
||||
client->ctl_bev = main_ctl->connect_bev;
|
||||
sync_new_work_connection(client->ctl_bev, client->stream_id);
|
||||
return;
|
||||
}
|
||||
|
||||
struct bufferevent *bev = connect_server(client->base, c_conf->server_addr, c_conf->server_port);
|
||||
if (!bev) {
|
||||
debug(LOG_DEBUG, "Connect server [%s:%d] failed", c_conf->server_addr, c_conf->server_port);
|
||||
@@ -142,10 +148,13 @@ static void
|
||||
start_proxy_services()
|
||||
{
|
||||
struct proxy_service *all_ps = get_all_proxy_services();
|
||||
assert(all_ps);
|
||||
|
||||
struct proxy_service *ps = NULL, *tmp = NULL;
|
||||
|
||||
if (!all_ps) {
|
||||
debug(LOG_INFO, "no proxy service configure by user");
|
||||
return;
|
||||
}
|
||||
|
||||
debug(LOG_INFO, "Start xfrp proxy services ...");
|
||||
|
||||
HASH_ITER(hh, all_ps, ps, tmp) {
|
||||
@@ -158,30 +167,23 @@ start_proxy_services()
|
||||
}
|
||||
|
||||
static void
|
||||
ping(struct bufferevent *bev)
|
||||
ping()
|
||||
{
|
||||
struct bufferevent *bout = NULL;
|
||||
if (bev) {
|
||||
bout = bev;
|
||||
} else {
|
||||
bout = main_ctl->connect_bev;
|
||||
}
|
||||
struct bufferevent *bout = main_ctl->connect_bev;
|
||||
|
||||
if ( ! bout) {
|
||||
debug(LOG_ERR, "bufferevent is not legal!");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t sid = get_main_control()->session_id;
|
||||
char *ping_msg = "{}";
|
||||
send_enc_msg_frp_server(bev, TypePing, ping_msg, strlen(ping_msg), sid);
|
||||
send_enc_msg_frp_server(bout, TypePing, ping_msg, strlen(ping_msg), main_ctl->stream_id);
|
||||
}
|
||||
|
||||
static void
|
||||
sync_new_work_connection(struct bufferevent *bev)
|
||||
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();
|
||||
@@ -197,8 +199,10 @@ sync_new_work_connection(struct bufferevent *bev)
|
||||
debug(LOG_ERR, "new work connection request run_id marshal failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
tcp_mux_send_win_update_syn(bev, sid);
|
||||
|
||||
send_msg_frp_server(bev, TypeNewWorkConn, new_work_conn_request_message, nret, 0);
|
||||
send_msg_frp_server(bev, TypeNewWorkConn, new_work_conn_request_message, nret, sid);
|
||||
|
||||
SAFE_FREE(new_work_conn_request_message);
|
||||
SAFE_FREE(work_c);
|
||||
@@ -232,13 +236,22 @@ set_ticker_ping_timer(struct event *timeout)
|
||||
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);
|
||||
|
||||
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
|
||||
@@ -286,29 +299,15 @@ proxy_service_resp_raw(struct new_proxy_response *npr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_all_unknown_encypt(uint8_t *enc_msg, int ilen)
|
||||
{
|
||||
uint8_t *iv = get_main_decoder()->iv;
|
||||
uint8_t *key = get_main_decoder()->key;
|
||||
FILE *fout = fopen("unkown.encrypt", "w");
|
||||
assert(fout);
|
||||
fwrite(iv, 16, 1, fout);
|
||||
fwrite(key, 16, 1, fout);
|
||||
fwrite((uint8_t *)&ilen, sizeof(int), 1, fout);
|
||||
fwrite(enc_msg, ilen, 1, fout);
|
||||
fclose(fout);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_enc_msg(uint8_t *enc_msg, int ilen, uint8_t **out)
|
||||
handle_enc_msg(const uint8_t *enc_msg, int ilen, uint8_t **out)
|
||||
{
|
||||
if (ilen <= 0) {
|
||||
debug(LOG_INFO, "enc_msg length should not be %d", ilen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *buf = enc_msg;
|
||||
const uint8_t *buf = enc_msg;
|
||||
if ( !is_decoder_inited() && get_block_size() <= ilen) {
|
||||
init_main_decoder(buf);
|
||||
buf += get_block_size();
|
||||
@@ -324,34 +323,25 @@ handle_enc_msg(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;
|
||||
}
|
||||
|
||||
static void
|
||||
print_enc_msg(uint8_t *enc_msg, int len)
|
||||
{
|
||||
printf("enc_msg is [%d]:\n", len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i%16 == 0)
|
||||
printf("\n");
|
||||
printf("%1x ", enc_msg[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
handle_control_work(const uint8_t *buf, int len, void *ctx)
|
||||
{
|
||||
uint8_t *frps_cmd = NULL;
|
||||
uint8_t cmd_type;
|
||||
uint8_t *enc_msg = buf;
|
||||
const uint8_t *enc_msg = buf;
|
||||
|
||||
if (!ctx)
|
||||
if (!ctx) {
|
||||
debug(LOG_DEBUG, "main control message");
|
||||
handle_enc_msg(enc_msg, len, &frps_cmd);
|
||||
else
|
||||
frps_cmd = buf;
|
||||
} else {
|
||||
debug(LOG_DEBUG, "worker message");
|
||||
frps_cmd = (uint8_t *)buf;
|
||||
}
|
||||
|
||||
if (!frps_cmd)
|
||||
return; // only recv iv
|
||||
@@ -359,10 +349,10 @@ handle_control_work(const uint8_t *buf, int len, void *ctx)
|
||||
struct msg_hdr *msg = (struct msg_hdr *)frps_cmd;
|
||||
|
||||
cmd_type = msg->type;
|
||||
debug(LOG_DEBUG, "cmd_type is %d data is %s", cmd_type, msg->data);
|
||||
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);
|
||||
@@ -370,8 +360,8 @@ handle_control_work(const uint8_t *buf, int len, void *ctx)
|
||||
new_client_connect();
|
||||
break;
|
||||
case TypeNewProxyResp:
|
||||
debug(LOG_DEBUG, "TypeNewProxyResp cmd");
|
||||
struct new_proxy_response *npr = new_proxy_resp_unmarshal(msg->data);
|
||||
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!");
|
||||
return;
|
||||
@@ -382,7 +372,7 @@ handle_control_work(const uint8_t *buf, int len, void *ctx)
|
||||
break;
|
||||
case TypeStartWorkConn:
|
||||
debug(LOG_DEBUG, "TypeStartWorkConn cmd");
|
||||
struct start_work_conn_resp *sr = start_work_conn_resp_unmarshal(msg->data);
|
||||
struct start_work_conn_resp *sr = start_work_conn_resp_unmarshal((const char *)msg->data);
|
||||
if (! sr) {
|
||||
debug(LOG_ERR,
|
||||
"TypeStartWorkConn unmarshal failed, it should never be happend!");
|
||||
@@ -417,11 +407,11 @@ 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);
|
||||
print_enc_msg(enc_msg, len);
|
||||
dump_all_unknown_encypt(enc_msg, len);
|
||||
}
|
||||
|
||||
if (!ctx)
|
||||
@@ -437,7 +427,7 @@ handle_login_response(const uint8_t *buf, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct login_resp *lres = login_resp_unmarshal(mhdr->data);
|
||||
struct login_resp *lres = login_resp_unmarshal((const char *)mhdr->data);
|
||||
if (!lres) {
|
||||
return 0;
|
||||
}
|
||||
@@ -452,14 +442,18 @@ handle_login_response(const uint8_t *buf, int len)
|
||||
is_login = 1;
|
||||
|
||||
int login_len = msg_hton(mhdr->length);
|
||||
debug(LOG_ERR, "login success! %d len %d", login_len, len);
|
||||
if (len-login_len-sizeof(struct msg_hdr) == 0)
|
||||
int ilen = len - login_len - sizeof(struct msg_hdr);
|
||||
debug(LOG_ERR, "login success! login_len %d len %d ilen %d", login_len, len, ilen);
|
||||
assert(ilen >= 0);
|
||||
if (ilen <= 0)
|
||||
return 1;
|
||||
|
||||
// in case, system get 3 packet together
|
||||
uint8_t *enc_msg = mhdr->data+login_len;
|
||||
// in case, libevent reveive continue packet together
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
assert(c_conf->tcp_mux == 0);
|
||||
uint8_t *enc_msg = mhdr->data + login_len;
|
||||
uint8_t *frps_cmd = NULL;
|
||||
int nret = handle_enc_msg(enc_msg, len-login_len-sizeof(struct msg_hdr), &frps_cmd);
|
||||
int nret = handle_enc_msg(enc_msg, ilen, &frps_cmd);
|
||||
assert(nret > 0);
|
||||
// start proxy services must first send
|
||||
start_proxy_services();
|
||||
@@ -472,18 +466,12 @@ handle_login_response(const uint8_t *buf, int len)
|
||||
}
|
||||
|
||||
static void
|
||||
handle_frps_msg(unsigned char *buf, int len, void *ctx)
|
||||
handle_frps_msg(uint8_t *buf, int len, void *ctx)
|
||||
{
|
||||
if (!is_login) {
|
||||
// login response
|
||||
handle_login_response(buf, len);
|
||||
}else if (!ctx) {
|
||||
// control msg
|
||||
debug(LOG_DEBUG, "main control message");
|
||||
handle_control_work(buf, len, NULL);
|
||||
}else {
|
||||
// client msg
|
||||
debug(LOG_DEBUG, "client message");
|
||||
handle_control_work(buf, len, ctx);
|
||||
}
|
||||
}
|
||||
@@ -499,12 +487,17 @@ recv_cb(struct bufferevent *bev, void *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char *buf = calloc(len+1, 1);
|
||||
uint8_t *buf = calloc(len+1, 1);
|
||||
assert(buf);
|
||||
evbuffer_remove(input, buf, len);
|
||||
debug(LOG_DEBUG, "recv msg from frps %d ", len);
|
||||
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
|
||||
handle_frps_msg(buf, len, ctx);
|
||||
if (c_conf->tcp_mux) {
|
||||
handle_tcp_mux_frps_msg(buf, len, handle_frps_msg);
|
||||
} else {
|
||||
handle_frps_msg(buf, len, ctx);
|
||||
}
|
||||
|
||||
SAFE_FREE(buf);
|
||||
return;
|
||||
@@ -514,38 +507,40 @@ static void
|
||||
connect_event_cb (struct bufferevent *bev, short what, void *ctx)
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
static int retry_times = 0;
|
||||
static int retry_times = 1;
|
||||
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
|
||||
if (retry_times >= 10) { // only try 10 times consecutively
|
||||
debug(LOG_ERR,
|
||||
"have retry connect to xfrp server for %d times, exit!",
|
||||
if (retry_times >= 100) {
|
||||
debug(LOG_INFO,
|
||||
"have retry connect to xfrp server for %d times, exit?",
|
||||
retry_times);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
sleep(2);
|
||||
retry_times++;
|
||||
debug(LOG_ERR, "error: connect server [%s:%d] failed",
|
||||
debug(LOG_ERR, "error: connect server [%s:%d] failed %s",
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port);
|
||||
free_control();
|
||||
init_main_control();
|
||||
start_base_connect();
|
||||
close_main_control();
|
||||
c_conf->server_port,
|
||||
strerror(errno));
|
||||
clear_main_control();
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -575,15 +570,19 @@ 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();
|
||||
if (main_ctl->connect_bev)
|
||||
bufferevent_free(main_ctl->connect_bev);
|
||||
|
||||
main_ctl->connect_bev = connect_server(main_ctl->connect_base,
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port);
|
||||
if ( ! main_ctl->connect_bev) {
|
||||
debug(LOG_ERR, "error: connect server [%s:%d] failed", c_conf->server_addr, c_conf->server_port);
|
||||
debug(LOG_ERR, "error: connect server [%s:%d] failed: [%d: %s]",
|
||||
c_conf->server_addr, c_conf->server_port, errno, strerror(errno));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -603,7 +602,7 @@ login()
|
||||
exit(0);
|
||||
}
|
||||
|
||||
send_msg_frp_server(NULL, TypeLogin, lg_msg, len, main_ctl->session_id);
|
||||
send_msg_frp_server(NULL, TypeLogin, lg_msg, len, 1);
|
||||
SAFE_FREE(lg_msg);
|
||||
}
|
||||
|
||||
@@ -622,15 +621,20 @@ send_msg_frp_server(struct bufferevent *bev,
|
||||
}
|
||||
assert(bout);
|
||||
|
||||
|
||||
|
||||
debug(LOG_DEBUG, "send plain msg ----> [%c: %s]", type, msg);
|
||||
|
||||
struct msg_hdr *req_msg = calloc(msg_len+sizeof(struct msg_hdr), 1);
|
||||
size_t len = msg_len + sizeof(struct msg_hdr);
|
||||
struct msg_hdr *req_msg = calloc(len, 1);
|
||||
assert(req_msg);
|
||||
req_msg->type = type;
|
||||
req_msg->length = msg_hton((uint64_t)msg_len);
|
||||
memcpy(req_msg->data, msg, msg_len);
|
||||
|
||||
bufferevent_write(bout, (uint8_t *)req_msg, msg_len+sizeof(struct msg_hdr));
|
||||
tcp_mux_send_data(bout, sid, len);
|
||||
|
||||
bufferevent_write(bout, (uint8_t *)req_msg, len);
|
||||
|
||||
free(req_msg);
|
||||
}
|
||||
@@ -660,6 +664,9 @@ send_enc_msg_frp_server(struct bufferevent *bev,
|
||||
|
||||
if (get_main_encoder() == NULL) {
|
||||
debug(LOG_DEBUG, "init_main_encoder .......");
|
||||
|
||||
tcp_mux_send_data(bout, sid, 16);
|
||||
|
||||
struct frp_coder *coder = init_main_encoder();
|
||||
bufferevent_write(bout, coder->iv, 16);
|
||||
}
|
||||
@@ -667,7 +674,9 @@ 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);
|
||||
|
||||
bufferevent_write(bout, enc_msg, olen);
|
||||
|
||||
@@ -717,7 +726,7 @@ send_new_proxy(struct proxy_service *ps)
|
||||
|
||||
debug(LOG_DEBUG, "control proxy client: [Type %d : proxy_name %s : msg_len %d]", TypeNewProxy, ps->proxy_name, len);
|
||||
|
||||
send_enc_msg_frp_server(NULL, TypeNewProxy, new_proxy_msg, len, main_ctl->session_id);
|
||||
send_enc_msg_frp_server(NULL, TypeNewProxy, new_proxy_msg, len, main_ctl->stream_id);
|
||||
SAFE_FREE(new_proxy_msg);
|
||||
}
|
||||
|
||||
@@ -733,14 +742,6 @@ init_main_control()
|
||||
assert(main_ctl);
|
||||
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
if (c_conf->tcp_mux) {
|
||||
uint32_t *sid = init_sid_index();
|
||||
assert(sid);
|
||||
main_ctl->session_id = *sid;
|
||||
|
||||
debug(LOG_DEBUG, "Connect Frps with control session ID: %d", main_ctl->session_id);
|
||||
}
|
||||
|
||||
struct event_base *base = NULL;
|
||||
struct evdns_base *dnsbase = NULL;
|
||||
base = event_base_new();
|
||||
@@ -749,6 +750,13 @@ init_main_control()
|
||||
exit(0);
|
||||
}
|
||||
main_ctl->connect_base = base;
|
||||
|
||||
if (c_conf->tcp_mux)
|
||||
main_ctl->stream_id = get_next_session_id();
|
||||
|
||||
// if server_addr is ip, done control init.
|
||||
if (is_valid_ip_address((const char *)c_conf->server_addr))
|
||||
return;
|
||||
|
||||
dnsbase = evdns_base_new(base, 1);
|
||||
if (! dnsbase) {
|
||||
@@ -767,10 +775,7 @@ init_main_control()
|
||||
evdns_base_nameserver_ip_add(dnsbase, "223.6.6.6"); //AliDNS
|
||||
evdns_base_nameserver_ip_add(dnsbase, "114.114.114.114"); //114DNS
|
||||
|
||||
// if server_addr is ip, done control init.
|
||||
if (is_valid_ip_address((const char *)c_conf->server_addr))
|
||||
return;
|
||||
|
||||
|
||||
// if server_addr is domain, analyze it to ip for server_ip
|
||||
debug(LOG_DEBUG, "Get ip address of [%s] from DNServer", c_conf->server_addr);
|
||||
|
||||
@@ -788,33 +793,48 @@ init_main_control()
|
||||
&hints,
|
||||
server_dns_cb,
|
||||
NULL);
|
||||
if (! dns_req) {
|
||||
if (!dns_req) {
|
||||
debug(LOG_ERR, "error: can not analyse the dns of [%s]", c_conf->server_addr);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_main_control()
|
||||
{
|
||||
SAFE_FREE(main_ctl);
|
||||
main_ctl = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_main_control()
|
||||
{
|
||||
assert(main_ctl);
|
||||
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
|
||||
close_main_control()
|
||||
{
|
||||
assert(main_ctl);
|
||||
clear_main_control();
|
||||
|
||||
event_base_dispatch(main_ctl->connect_base);
|
||||
event_base_free(main_ctl->connect_base);
|
||||
evdns_base_free(main_ctl->dnsbase, 0);
|
||||
event_base_free(main_ctl->connect_base);
|
||||
|
||||
free_main_control();
|
||||
}
|
||||
|
||||
void
|
||||
run_control()
|
||||
{
|
||||
start_base_connect();
|
||||
keep_control_alive();
|
||||
}
|
||||
|
||||
void
|
||||
free_control()
|
||||
{
|
||||
if (!main_ctl)
|
||||
return;
|
||||
|
||||
SAFE_FREE(main_ctl);
|
||||
}
|
||||
|
||||
19
control.h
19
control.h
@@ -40,21 +40,28 @@ struct control {
|
||||
struct event_base *connect_base; //main netevent
|
||||
struct evdns_base *dnsbase;
|
||||
struct bufferevent *connect_bev; //main io evet buf
|
||||
char session_id;
|
||||
struct event *ticker_ping; //heartbeat timer
|
||||
|
||||
struct event *tcp_mux_ping_event;
|
||||
uint32_t tcp_mux_ping_id;
|
||||
uint32_t stream_id;
|
||||
};
|
||||
|
||||
void connect_eventcb(struct bufferevent *bev, short events, void *ptr);
|
||||
void start_base_connect();
|
||||
|
||||
void init_main_control();
|
||||
|
||||
void run_control();
|
||||
|
||||
struct control *get_main_control();
|
||||
|
||||
void close_main_control();
|
||||
|
||||
void start_login_frp_server(struct event_base *base);
|
||||
|
||||
void send_login_frp_server(struct bufferevent *bev);
|
||||
|
||||
void login();
|
||||
void free_control();
|
||||
void sync_session_id(uint32_t sid);
|
||||
|
||||
void send_msg_frp_server(struct bufferevent *bev,
|
||||
const enum msg_type type,
|
||||
@@ -69,9 +76,9 @@ void send_enc_msg_frp_server(struct bufferevent *bev,
|
||||
uint32_t sid);
|
||||
|
||||
void control_process(struct proxy_client *client);
|
||||
|
||||
void send_new_proxy(struct proxy_service *ps);
|
||||
|
||||
struct bufferevent
|
||||
*connect_server(struct event_base *base, const char *name, const int port);
|
||||
struct bufferevent *connect_server(struct event_base *base, const char *name, const int port);
|
||||
|
||||
#endif //_CONTROL_H_
|
||||
|
||||
101
crypto.c
101
crypto.c
@@ -1,3 +1,30 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file crypto.c
|
||||
@brief xfrpc crypto implement
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -16,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()
|
||||
@@ -29,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);
|
||||
@@ -67,7 +134,7 @@ init_main_encoder()
|
||||
}
|
||||
|
||||
struct frp_coder *
|
||||
init_main_decoder(unsigned char *iv)
|
||||
init_main_decoder(const uint8_t *iv)
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
main_decoder = new_coder(c_conf->auth_token, default_salt);
|
||||
@@ -132,19 +199,11 @@ encrypt_iv(unsigned char *iv_buf, size_t iv_len)
|
||||
return iv_buf;
|
||||
}
|
||||
|
||||
static void
|
||||
print_hex(uint8_t *val, size_t len)
|
||||
{
|
||||
for(int i = 0; i < len; i++)
|
||||
printf("%1x", val[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// using aes-128-cfb and nopadding
|
||||
size_t
|
||||
encrypt_data(const unsigned char *src_data, size_t srclen, struct frp_coder *encoder, unsigned char **ret)
|
||||
encrypt_data(const uint8_t *src_data, size_t srclen, struct frp_coder *encoder, unsigned char **ret)
|
||||
{
|
||||
uint8_t *intext = src_data;
|
||||
uint8_t *intext = (uint8_t *)src_data;
|
||||
assert(intext);
|
||||
assert(encoder);
|
||||
struct frp_coder *c = encoder;
|
||||
@@ -156,11 +215,11 @@ encrypt_data(const unsigned char *src_data, size_t srclen, struct frp_coder *enc
|
||||
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!");
|
||||
@@ -180,7 +239,7 @@ E_END:
|
||||
size_t
|
||||
decrypt_data(const uint8_t *enc_data, size_t enclen, struct frp_coder *decoder, uint8_t **ret)
|
||||
{
|
||||
uint8_t *inbuf = enc_data;
|
||||
uint8_t *inbuf = (uint8_t *)enc_data;
|
||||
uint8_t *outbuf = calloc(enclen+1, 1);
|
||||
struct frp_coder *c = decoder;
|
||||
assert(inbuf);
|
||||
@@ -189,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;
|
||||
|
||||
36
crypto.h
36
crypto.h
@@ -1,3 +1,30 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file crypto.h
|
||||
@brief xfrpc crypto header
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _CRYPTO_H_
|
||||
#define _CRYPTO_H_
|
||||
|
||||
@@ -15,18 +42,19 @@ struct frp_coder {
|
||||
};
|
||||
|
||||
size_t get_encrypt_block_size();
|
||||
size_t decrypt_data(const unsigned char *enc_data, size_t enc_len, struct frp_coder *decoder, unsigned char **ret);
|
||||
size_t decrypt_data(const uint8_t *enc_data, size_t enc_len, struct frp_coder *decoder, uint8_t **ret);
|
||||
int is_encoder_inited();
|
||||
int is_decoder_inited();
|
||||
struct frp_coder *init_main_encoder();
|
||||
struct frp_coder *init_main_decoder(unsigned char *iv);
|
||||
struct frp_coder *init_main_decoder(const uint8_t *iv);
|
||||
struct frp_coder *new_coder(const char *privilege_token, const char *salt);
|
||||
uint8_t *encrypt_key(const char *token, size_t token_len, const char *salt, uint8_t *key, size_t key_len);
|
||||
uint8_t *encrypt_iv(unsigned char *iv_buf, size_t iv_len);
|
||||
size_t encrypt_data(const unsigned char *src_data, size_t srclen, struct frp_coder *encoder, unsigned char **ret);
|
||||
uint8_t *encrypt_iv(uint8_t *iv_buf, size_t iv_len);
|
||||
size_t encrypt_data(const uint8_t *src_data, size_t srclen, struct frp_coder *encoder, uint8_t **ret);
|
||||
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_
|
||||
|
||||
6
debug.c
6
debug.c
@@ -34,6 +34,8 @@
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#define PROGNAME "xfrpc"
|
||||
|
||||
debugconf_t debugconf = {
|
||||
.debuglevel = LOG_INFO,
|
||||
.log_stderr = 1,
|
||||
@@ -46,7 +48,7 @@ Do not use directly, use the debug macro */
|
||||
void
|
||||
_debug(const char *filename, int line, int level, const char *format, ...)
|
||||
{
|
||||
char buf[28];
|
||||
char buf[32] = {0};
|
||||
va_list vlist;
|
||||
time_t ts;
|
||||
sigset_t block_chld;
|
||||
@@ -75,7 +77,7 @@ _debug(const char *filename, int line, int level, const char *format, ...)
|
||||
}
|
||||
|
||||
if (debugconf.log_syslog) {
|
||||
openlog("wifidog", LOG_PID, debugconf.syslog_facility);
|
||||
openlog(PROGNAME, LOG_PID, debugconf.syslog_facility);
|
||||
va_start(vlist, format);
|
||||
vsyslog(level, format, vlist);
|
||||
va_end(vlist);
|
||||
|
||||
1
debug.h
1
debug.h
@@ -28,6 +28,7 @@
|
||||
#define _WIFIDOG_DEBUG_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
|
||||
|
||||
26
login.c
26
login.c
@@ -1,3 +1,29 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file login.c
|
||||
@brief xfrpc login protocol implemented
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
26
login.h
26
login.h
@@ -1,3 +1,29 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file login.h
|
||||
@brief xfrp login header
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#ifndef _LOGIN_H_
|
||||
#define _LOGIN_H_
|
||||
|
||||
|
||||
17
msg.c
17
msg.c
@@ -20,7 +20,7 @@
|
||||
\********************************************************************/
|
||||
|
||||
/** @file msg.c
|
||||
@brief xfrp client msg related
|
||||
@brief xfrpc client msg related
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
@@ -48,7 +48,7 @@ json_object_object_add(jobj, key, json_object_new_##jtype((item)));
|
||||
#define SAFE_JSON_STRING(str_target) \
|
||||
str_target?str_target:"\0"
|
||||
|
||||
const char msg_typs[] = {TypeLogin,
|
||||
const char msg_types[] = {TypeLogin,
|
||||
TypeLoginResp,
|
||||
TypeNewProxy,
|
||||
TypeNewProxyResp,
|
||||
@@ -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))
|
||||
@@ -388,11 +387,17 @@ int
|
||||
msg_type_valid_check(char msg_type)
|
||||
{
|
||||
int i = 0;
|
||||
for(i = 0; i<(sizeof(msg_typs) / sizeof(*msg_typs)); i++) {
|
||||
if (msg_typs[i] == msg_type)
|
||||
for(i = 0; i<(sizeof(msg_types) / sizeof(*msg_types)); i++) {
|
||||
if (msg_types[i] == msg_type)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
get_msg_type(uint8_t type)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
4
msg.h
4
msg.h
@@ -20,7 +20,7 @@
|
||||
\********************************************************************/
|
||||
|
||||
/** @file msg.h
|
||||
@brief xfrp msg struct
|
||||
@brief xfrpc msg struct
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
@@ -114,4 +114,6 @@ int new_work_conn_marshal(const struct work_conn *work_c, char **msg);
|
||||
|
||||
void control_response_free(struct control_response *res);
|
||||
|
||||
char *get_msg_type(uint8_t type);
|
||||
|
||||
#endif //_MSG_H_
|
||||
|
||||
@@ -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,31 +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 auth_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 'ftp01'
|
||||
# option type ftp
|
||||
# option local_ip 127.0.01
|
||||
# option local_port 21
|
||||
# option remote_port 8021
|
||||
# option remote_data_port 8022
|
||||
|
||||
#config xfrpc 'web01'
|
||||
# option type http
|
||||
# option local_ip 127.0.0.1
|
||||
# option local_port 8080
|
||||
|
||||
#config xfrpc 'web02'
|
||||
# option type https
|
||||
# option local_ip 127.0.0.1
|
||||
# option local_port 8443
|
||||
@@ -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' \
|
||||
'auth_token:string'
|
||||
|
||||
[ -z "$auth_token" ] && {
|
||||
echo "no auth_token"
|
||||
exit
|
||||
}
|
||||
echo "server_addr = $server_addr" >> "$config"
|
||||
echo "server_port = $server_port" >> "$config"
|
||||
echo "auth_token = $auth_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
|
||||
}
|
||||
30
proxy.c
30
proxy.c
@@ -1,3 +1,29 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file proxy.c
|
||||
@brief xfrp proxy implemented
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
@@ -8,10 +34,6 @@
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "uthash.h"
|
||||
|
||||
26
proxy.h
26
proxy.h
@@ -1,3 +1,29 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file proxy.h
|
||||
@brief xfrp proxy header file
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#ifndef _PROXY_H_
|
||||
#define _PROXY_H_
|
||||
|
||||
|
||||
68
proxy_tcp.c
68
proxy_tcp.c
@@ -1,3 +1,29 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file proxy_tcp.c
|
||||
@brief xfrp proxy tcp implemented
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
@@ -7,6 +33,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
@@ -17,25 +44,50 @@
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
#include "config.h"
|
||||
#include "tcpmux.h"
|
||||
|
||||
#define BUF_LEN 4096
|
||||
|
||||
// read data from local service
|
||||
void tcp_proxy_c2s_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
struct proxy_client *client = (struct proxy_client *)ctx;
|
||||
assert(client);
|
||||
struct bufferevent *partner = client->ctl_bev;
|
||||
assert(partner);
|
||||
struct evbuffer *src, *dst;
|
||||
size_t len;
|
||||
src = bufferevent_get_input(bev);
|
||||
len = evbuffer_get_length(src);
|
||||
if (len > 0) {
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
struct evbuffer *src = bufferevent_get_input(bev);
|
||||
size_t len = evbuffer_get_length(src);
|
||||
assert(len > 0);
|
||||
if (!c_conf->tcp_mux) {
|
||||
struct evbuffer *dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->send_window == 0) {
|
||||
debug(LOG_DEBUG, "client %d recv len %d exceed send windows: %d", client->stream_id, len, client->send_window);
|
||||
bufferevent_disable(bev, EV_READ);
|
||||
return;
|
||||
} else {
|
||||
len = client->send_window>=len?len:client->send_window;
|
||||
client->send_window -= len;
|
||||
}
|
||||
|
||||
tcp_mux_send_data(partner, client->stream_id, len);
|
||||
uint8_t buf[BUF_LEN];
|
||||
while(len > 0) {
|
||||
memset(buf, 0, BUF_LEN);
|
||||
int nread = bufferevent_read(bev, buf, len>BUF_LEN?BUF_LEN:len);
|
||||
assert(nread >= 0);
|
||||
bufferevent_write(partner, buf, nread);
|
||||
len -= nread;
|
||||
}
|
||||
}
|
||||
|
||||
// read data from frps
|
||||
// when tcp mux enable this function will not be used
|
||||
void tcp_proxy_s2c_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct proxy_client *client = (struct proxy_client *)ctx;
|
||||
@@ -44,6 +96,8 @@ void tcp_proxy_s2c_cb(struct bufferevent *bev, void *ctx)
|
||||
assert(partner);
|
||||
struct evbuffer *src, *dst;
|
||||
src = bufferevent_get_input(bev);
|
||||
size_t len = evbuffer_get_length(src);
|
||||
assert(len > 0);
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
}
|
||||
|
||||
54
session.c
54
session.c
@@ -1,54 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "uthash.h"
|
||||
#include "session.h"
|
||||
#include "version.h"
|
||||
#include "debug.h"
|
||||
|
||||
uint32_t *sid_index = NULL;
|
||||
|
||||
// need free
|
||||
uint32_t *
|
||||
init_sid_index()
|
||||
{
|
||||
if (NULL == sid_index) {
|
||||
sid_index = (uint32_t *)calloc(1, sizeof(uint32_t));
|
||||
if (NULL == sid_index)
|
||||
return sid_index;
|
||||
|
||||
#ifdef CLIENT_V
|
||||
*sid_index = 1;
|
||||
#elif SERVER
|
||||
*sid_index = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
*sid_index += 2; //xfrp client session id start from 3
|
||||
return sid_index;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
get_current_sid_index()
|
||||
{
|
||||
if (NULL == sid_index) {
|
||||
return *init_sid_index();
|
||||
}
|
||||
|
||||
return *sid_index;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
new_sid()
|
||||
{
|
||||
if (NULL == sid_index) {
|
||||
init_sid_index();
|
||||
return get_current_sid_index();
|
||||
}
|
||||
|
||||
*sid_index += 2;
|
||||
return *sid_index;
|
||||
}
|
||||
11
session.h
11
session.h
@@ -1,11 +0,0 @@
|
||||
#ifndef _SESSION_H_
|
||||
#define _SESSION_H_
|
||||
|
||||
#include "uthash.h"
|
||||
#include "common.h"
|
||||
|
||||
uint32_t *init_sid_index();
|
||||
uint32_t get_current_sid_index();
|
||||
uint32_t new_sid();
|
||||
|
||||
#endif //_SESSION_H_
|
||||
16
systemd/xfrpc.service
Normal file
16
systemd/xfrpc.service
Normal file
@@ -0,0 +1,16 @@
|
||||
# 1. put xfrpc and xfrpc.ini under /usr/local/xfrpc/
|
||||
# 2. put this file (xfrpc.service) at /etc/systemd/system
|
||||
# 3. run `sudo systemctl daemon-reload && sudo systemctl enable xfrpc && sudo systemctl start xfrpc`
|
||||
# Then we can manage xfrpc with `sudo service xfrpc {start|stop|restart|status}`
|
||||
|
||||
|
||||
[Unit]
|
||||
Description=frp c language client
|
||||
Wants=network-online.target
|
||||
After=network.target network-online.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/xfrpc/xfrpc -c /usr/local/xfrpc/xfrpc.ini -f -d 0
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
368
tcpmux.c
Normal file
368
tcpmux.c
Normal file
@@ -0,0 +1,368 @@
|
||||
/* vim: set et ts=4 sts=4 sw=4 : */
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file tcpmux.c
|
||||
@brief xfrp tcp mux implemented
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "tcpmux.h"
|
||||
#include "client.h"
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "control.h"
|
||||
|
||||
static uint8_t proto_version = 0;
|
||||
|
||||
static struct tcp_mux_type_desc type_desc[] = {
|
||||
{DATA, "data"},
|
||||
{WINDOW_UPDATE, "window update"},
|
||||
{PING, "ping"},
|
||||
{GO_AWAY, "go away"},
|
||||
};
|
||||
|
||||
static struct tcp_mux_flag_desc flag_desc[] = {
|
||||
{ZERO, "zero"},
|
||||
{SYN, "syn"},
|
||||
{ACK, "ack"},
|
||||
{FIN, "fin"},
|
||||
{RST, "rst"},
|
||||
};
|
||||
|
||||
static const char *
|
||||
type_2_desc(enum tcp_mux_type type)
|
||||
{
|
||||
for(int i = 0; i < sizeof(type_desc)/sizeof(struct tcp_mux_type_desc); i++){
|
||||
if (type == type_desc[i].type)
|
||||
return type_desc[i].desc;
|
||||
}
|
||||
|
||||
return "unkown_type";
|
||||
}
|
||||
|
||||
static const char *
|
||||
flag_2_desc(enum tcp_mux_flag flag)
|
||||
{
|
||||
for(int i = 0; i < sizeof(flag_desc)/sizeof(struct tcp_mux_flag_desc); i++){
|
||||
if (flag == flag_desc[i].flag)
|
||||
return flag_desc[i].desc;
|
||||
}
|
||||
|
||||
return "unkown_flag";
|
||||
}
|
||||
|
||||
static int
|
||||
valid_tcp_mux_type(uint8_t type)
|
||||
{
|
||||
if (type >= DATA && type <= GO_AWAY)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
valid_tcp_mux_sid(uint32_t sid)
|
||||
{
|
||||
if (sid == 1)
|
||||
return 1;
|
||||
|
||||
return get_proxy_client(sid)?1:0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tcp_mux_encode(enum tcp_mux_type type, enum tcp_mux_flag flags, uint32_t stream_id, uint32_t length, struct tcp_mux_header *tmux_hdr)
|
||||
{
|
||||
assert(tmux_hdr);
|
||||
tmux_hdr->version = proto_version;
|
||||
tmux_hdr->type = type;
|
||||
tmux_hdr->flags = htons(flags);
|
||||
tmux_hdr->stream_id = htonl(stream_id);
|
||||
tmux_hdr->length = length?htonl(length):0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
tcp_mux_flag()
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
return c_conf->tcp_mux;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_tcp_mux_header(uint8_t *data, int len)
|
||||
{
|
||||
if (len != 12)
|
||||
return;
|
||||
|
||||
printf("tcp mux header is : \n");
|
||||
for (int i = 0; i < len; i++)
|
||||
printf("%2x", data[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
parse_tcp_mux_proto(uint8_t *data, int len, uint32_t *flag, uint32_t *type, uint32_t *stream_id, uint32_t *dlen)
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
if (!c_conf->tcp_mux)
|
||||
return 0;
|
||||
|
||||
if (len < sizeof(struct tcp_mux_header))
|
||||
return 0;
|
||||
|
||||
struct tcp_mux_header *hdr = (struct tcp_mux_header *)data;
|
||||
if(hdr->version == proto_version &&
|
||||
valid_tcp_mux_type(hdr->type)) {
|
||||
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));
|
||||
dump_tcp_mux_header(data, len);
|
||||
exit(-1);
|
||||
}
|
||||
*type = hdr->type;
|
||||
*flag = htons(hdr->flags);
|
||||
*stream_id = htonl(hdr->stream_id);
|
||||
*dlen = htonl(hdr->length);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
get_next_session_id() {
|
||||
static uint32_t next_session_id = 1;
|
||||
uint32_t id = next_session_id;
|
||||
next_session_id += 2;
|
||||
return id;
|
||||
}
|
||||
|
||||
void
|
||||
tcp_mux_send_win_update_syn(struct bufferevent *bout, uint32_t stream_id)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
struct tcp_mux_header tmux_hdr;
|
||||
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
|
||||
tcp_mux_encode(WINDOW_UPDATE, SYN, stream_id, 0, &tmux_hdr);
|
||||
debug(LOG_DEBUG, "tcp mux [%d] send wind update syn", stream_id);
|
||||
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
|
||||
}
|
||||
|
||||
void
|
||||
tcp_mux_send_win_update_ack(struct bufferevent *bout, uint32_t stream_id, uint32_t delta)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
struct tcp_mux_header tmux_hdr;
|
||||
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
|
||||
tcp_mux_encode(WINDOW_UPDATE, ZERO, stream_id, delta, &tmux_hdr);
|
||||
debug(LOG_DEBUG, "tcp mux [%d] send wind update ZERO [%d]", stream_id, delta);
|
||||
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
|
||||
}
|
||||
|
||||
void
|
||||
tcp_mux_send_win_update_fin(struct bufferevent *bout, uint32_t stream_id)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
struct tcp_mux_header tmux_hdr;
|
||||
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
|
||||
tcp_mux_encode(WINDOW_UPDATE, FIN, stream_id, 0, &tmux_hdr);
|
||||
debug(LOG_DEBUG, "tcp mux [%d] send wind update FIN", stream_id);
|
||||
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
|
||||
}
|
||||
|
||||
void
|
||||
tcp_mux_send_data(struct bufferevent *bout, uint32_t stream_id, uint32_t length)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
struct tcp_mux_header tmux_hdr;
|
||||
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
|
||||
tcp_mux_encode(DATA, ZERO, stream_id, length, &tmux_hdr);
|
||||
//debug(LOG_DEBUG, "tcp mux [%d] send data len : %d", stream_id, length);
|
||||
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
|
||||
}
|
||||
|
||||
void
|
||||
tcp_mux_send_ping(struct bufferevent *bout, uint32_t ping_id)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
struct tcp_mux_header tmux_hdr;
|
||||
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
|
||||
tcp_mux_encode(PING, SYN, 0, ping_id, &tmux_hdr);
|
||||
//debug(LOG_DEBUG, "tcp mux send ping syn : %d", ping_id);
|
||||
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
|
||||
}
|
||||
|
||||
static void
|
||||
tcp_mux_handle_ping(struct bufferevent *bout, uint32_t ping_id)
|
||||
{
|
||||
if (!tcp_mux_flag()) return;
|
||||
|
||||
struct tcp_mux_header tmux_hdr;
|
||||
memset(&tmux_hdr, 0, sizeof(tmux_hdr));
|
||||
tcp_mux_encode(PING, ACK, 0, ping_id, &tmux_hdr);
|
||||
//debug(LOG_DEBUG, "tcp mux send ping ack : %d", ping_id);
|
||||
bufferevent_write(bout, (uint8_t *)&tmux_hdr, sizeof(tmux_hdr));
|
||||
}
|
||||
|
||||
void
|
||||
handle_tcp_mux_frps_msg(uint8_t *buf, int ilen, void (*fn)(uint8_t *, int, void *))
|
||||
{
|
||||
static uint32_t l_stream_id = 0;
|
||||
static uint32_t l_dlen = 0;
|
||||
static uint32_t l_type = 0;
|
||||
static uint32_t l_flag = 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);
|
||||
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",
|
||||
!pc?"main control ":"worker ",
|
||||
l_stream_id, type_2_desc(l_type),
|
||||
flag_2_desc(l_flag), l_dlen, ilen);
|
||||
assert(ilen);
|
||||
if (ilen == 12)
|
||||
dump_tcp_mux_header(data, ilen);
|
||||
|
||||
if (!pc || (pc && !pc->local_proxy_bev)) {
|
||||
assert(ilen >= l_dlen);
|
||||
assert(l_dlen > 0);
|
||||
fn(data, l_dlen, pc);
|
||||
data += l_dlen;
|
||||
ilen -= l_dlen;
|
||||
l_dlen = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pc->stream_state != ESTABLISHED) {
|
||||
debug(LOG_INFO, "client [%d] state is [%d]", pc->stream_id, pc->stream_state);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ilen >= l_dlen) {
|
||||
assert(pc->local_proxy_bev);
|
||||
bufferevent_write(pc->local_proxy_bev, data, l_dlen);
|
||||
data += l_dlen;
|
||||
ilen -= l_dlen;
|
||||
l_dlen = 0;
|
||||
} else {
|
||||
assert(pc->local_proxy_bev);
|
||||
bufferevent_write(pc->local_proxy_bev, data, ilen);
|
||||
l_dlen -= ilen;
|
||||
ilen = 0;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
struct proxy_client *pc = get_proxy_client(stream_id);
|
||||
debug(LOG_DEBUG, "[%s] receive tcp mux type [%s] flag [%s] stream_id [%d] dlen [%d] ilen [%d]",
|
||||
pc?"worker":"main control",
|
||||
type_2_desc(type), flag_2_desc(flag), stream_id, dlen, ilen);
|
||||
data += sizeof(struct tcp_mux_header);
|
||||
ilen -= sizeof(struct tcp_mux_header);
|
||||
l_stream_id = stream_id;
|
||||
l_type = type;
|
||||
l_flag = flag;
|
||||
l_dlen = type==PING?0:dlen;
|
||||
assert(ilen >= 0);
|
||||
|
||||
switch(type) {
|
||||
case DATA:
|
||||
{
|
||||
if (ilen == 0)
|
||||
break;
|
||||
|
||||
if (!pc || (pc && !pc->local_proxy_bev)) {
|
||||
assert(ilen >= dlen);
|
||||
fn(data, dlen, pc);
|
||||
data += dlen;
|
||||
ilen -= dlen;
|
||||
l_dlen = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pc->stream_state != ESTABLISHED) {
|
||||
debug(LOG_INFO, "client [%d] state is [%d]", pc->stream_id, pc->stream_state);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ilen >= dlen){
|
||||
assert(pc->local_proxy_bev);
|
||||
bufferevent_write(pc->local_proxy_bev, data, dlen);
|
||||
data += dlen;
|
||||
ilen -= dlen;
|
||||
l_dlen = 0;
|
||||
} else {
|
||||
assert(pc->local_proxy_bev);
|
||||
bufferevent_write(pc->local_proxy_bev, data, ilen);
|
||||
l_dlen -= ilen;
|
||||
ilen = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PING:
|
||||
{
|
||||
struct bufferevent *bout = get_main_control()->connect_bev;
|
||||
uint32_t seq = dlen;
|
||||
assert(bout);
|
||||
if (flag == SYN)
|
||||
tcp_mux_handle_ping(bout, seq);
|
||||
break;
|
||||
}
|
||||
case WINDOW_UPDATE:
|
||||
{
|
||||
switch(flag) {
|
||||
case RST:
|
||||
case FIN:
|
||||
del_proxy_client(pc);
|
||||
break;
|
||||
case ZERO:
|
||||
case ACK:
|
||||
if (!pc)
|
||||
break;
|
||||
|
||||
if (dlen > 0) {
|
||||
pc->send_window += dlen;
|
||||
bufferevent_enable(pc->local_proxy_bev, EV_READ|EV_WRITE);
|
||||
}
|
||||
pc->stream_state = ESTABLISHED;
|
||||
break;
|
||||
default:
|
||||
debug(LOG_INFO, "window update no need process : flag %2x %s dlen %d stream_id %d",
|
||||
flag, flag_2_desc(flag), dlen, stream_id);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
debug(LOG_INFO, "no need unhandle tcp mux msg : type %s flag %s stream_id %d dlen %d ilen %d",
|
||||
type_2_desc(type), flag_2_desc(flag), stream_id, dlen, ilen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,74 @@
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
/** @file agent.c
|
||||
@brief agent for router to communicate with frp server
|
||||
/** @file tcpmux.h
|
||||
@brief xfrp tcp mux header file
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
#ifndef __TCP_MUX__
|
||||
#define __TCP_MUX__
|
||||
|
||||
#include "uthash.h"
|
||||
|
||||
enum tcp_mux_type {
|
||||
DATA,
|
||||
WINDOW_UPDATE,
|
||||
PING,
|
||||
GO_AWAY,
|
||||
};
|
||||
|
||||
struct tcp_mux_type_desc {
|
||||
enum tcp_mux_type type;
|
||||
char *desc;
|
||||
};
|
||||
|
||||
enum tcp_mux_flag {
|
||||
ZERO,
|
||||
SYN,
|
||||
ACK = 1<<1,
|
||||
FIN = 1<<2,
|
||||
RST = 1<<3,
|
||||
};
|
||||
|
||||
struct __attribute__((__packed__)) tcp_mux_header {
|
||||
uint8_t version;
|
||||
uint8_t type;
|
||||
uint16_t flags;
|
||||
uint32_t stream_id;
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
struct tcp_mux_flag_desc {
|
||||
enum tcp_mux_flag flag;
|
||||
char *desc;
|
||||
};
|
||||
|
||||
enum tcp_mux_state {
|
||||
INIT = 0,
|
||||
SYN_SEND,
|
||||
SYN_RECEIVED,
|
||||
ESTABLISHED,
|
||||
LOCAL_CLOSE,
|
||||
REMOTE_CLOSE,
|
||||
CLOSED,
|
||||
RESET
|
||||
};
|
||||
|
||||
void tcp_mux_send_win_update_syn(struct bufferevent *bout, uint32_t stream_id);
|
||||
|
||||
void tcp_mux_send_win_update_ack(struct bufferevent *bout, uint32_t stream_id, uint32_t delta);
|
||||
|
||||
void tcp_mux_send_win_update_fin(struct bufferevent *bout, uint32_t stream_id);
|
||||
|
||||
void tcp_mux_send_data(struct bufferevent *bout, uint32_t stream_id, uint32_t length);
|
||||
|
||||
void tcp_mux_send_ping(struct bufferevent *bout, uint32_t ping_id);
|
||||
|
||||
uint32_t get_next_session_id();
|
||||
|
||||
void tcp_mux_encode(enum tcp_mux_type type, enum tcp_mux_flag flags, uint32_t stream_id, uint32_t length, struct tcp_mux_header *tmux_hdr);
|
||||
|
||||
void handle_tcp_mux_frps_msg(uint8_t *data, int len, void (*fn)(uint8_t *, int, void *));
|
||||
|
||||
#endif
|
||||
@@ -1,8 +1,8 @@
|
||||
#ifndef _VERSION_H_
|
||||
#define _VERSION_H_
|
||||
|
||||
#define VERSION "1.41.1"
|
||||
#define PROTOCOL_VERESION "0.41.0"
|
||||
#define VERSION "1.05.579"
|
||||
#define PROTOCOL_VERESION "0.43.0"
|
||||
#define CLIENT_V 1
|
||||
|
||||
#endif //_VERSION_H_
|
||||
|
||||
2
xfrpc.c
2
xfrpc.c
@@ -20,7 +20,7 @@
|
||||
\********************************************************************/
|
||||
|
||||
/** @file xfrpc.c
|
||||
@brief xfrp client
|
||||
@brief xfrpc client
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
|
||||
4
xfrpc.h
4
xfrpc.h
@@ -20,7 +20,7 @@
|
||||
\********************************************************************/
|
||||
|
||||
/** @file xfrpc.h
|
||||
@brief xfrp client header file
|
||||
@brief xfrpc client header file
|
||||
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
|
||||
*/
|
||||
|
||||
@@ -29,4 +29,4 @@
|
||||
|
||||
void xfrpc_loop();
|
||||
|
||||
#endif //_XFRPC_H_
|
||||
#endif //_XFRPC_H_
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
[common]
|
||||
server_addr = your_server_ip
|
||||
server_port = 7000
|
||||
token = 12345678
|
||||
|
||||
[ssh]
|
||||
type = tcp
|
||||
|
||||
Reference in New Issue
Block a user