Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2429f79721 | ||
|
|
044626152c | ||
|
|
0d7643ceb1 | ||
|
|
0e581ebf6f | ||
|
|
2fcfa6a001 | ||
|
|
546dfb74d3 | ||
|
|
a02a5a19c7 | ||
|
|
09b67f7dc6 | ||
|
|
731584cbd3 | ||
|
|
25a994213f | ||
|
|
c4a9f4c97e | ||
|
|
a56d0d4d58 | ||
|
|
9f01265981 | ||
|
|
1e96d85f88 | ||
|
|
a668a6deff | ||
|
|
9ae47ffaa4 | ||
|
|
8d1c6f69ca | ||
|
|
4bcc36489b | ||
|
|
e9e2bf759a | ||
|
|
c6e3af8ac8 | ||
|
|
5ab2ac455d | ||
|
|
ddc3aff29b | ||
|
|
8f75d7c40c | ||
|
|
3c02e4fbc4 | ||
|
|
5b2b3a63ab | ||
|
|
b96e3d9364 | ||
|
|
f9636ce89c | ||
|
|
c1b7585cd5 |
@@ -20,6 +20,9 @@ set(src_xfrpc
|
||||
session.c
|
||||
common.c
|
||||
login.c
|
||||
proxy_tcp.c
|
||||
proxy_ftp.c
|
||||
proxy.c
|
||||
)
|
||||
|
||||
set(libs
|
||||
|
||||
93
client.c
93
client.c
@@ -52,8 +52,8 @@
|
||||
#include "const.h"
|
||||
#include "uthash.h"
|
||||
#include "zip.h"
|
||||
#include "msg.h"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
|
||||
#define MAX_OUTPUT (512*1024)
|
||||
|
||||
@@ -63,7 +63,8 @@ static void xfrp_event_cb(struct bufferevent *bev, short what, void *ctx);
|
||||
static void
|
||||
xfrp_read_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
struct evbuffer *src, *dst;
|
||||
size_t len;
|
||||
src = bufferevent_get_input(bev);
|
||||
@@ -74,13 +75,14 @@ xfrp_read_cb(struct bufferevent *bev, void *ctx)
|
||||
}
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
struct proxy *p_l = new_proxy_buf(bev);
|
||||
|
||||
if (evbuffer_get_length(dst) >= MAX_OUTPUT) {
|
||||
/* We're giving the other side data faster than it can
|
||||
* pass it on. Stop reading here until we have drained the
|
||||
* other side to MAX_OUTPUT/2 bytes. */
|
||||
bufferevent_setcb(partner, xfrp_read_cb, drained_writecb,
|
||||
xfrp_event_cb, bev);
|
||||
xfrp_event_cb, p_l);
|
||||
bufferevent_setwatermark(partner, EV_WRITE, MAX_OUTPUT/2,
|
||||
MAX_OUTPUT);
|
||||
bufferevent_disable(bev, EV_READ);
|
||||
@@ -90,11 +92,12 @@ xfrp_read_cb(struct bufferevent *bev, void *ctx)
|
||||
static void
|
||||
drained_writecb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
|
||||
/* We were choking the other side until we drained our outbuf a bit.
|
||||
* Now it seems drained. */
|
||||
bufferevent_setcb(bev, xfrp_read_cb, NULL, xfrp_event_cb, partner);
|
||||
bufferevent_setcb(bev, xfrp_read_cb, NULL, xfrp_event_cb, p);
|
||||
bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
|
||||
if (partner)
|
||||
bufferevent_enable(partner, EV_READ);
|
||||
@@ -113,13 +116,14 @@ close_on_finished_writecb(struct bufferevent *bev, void *ctx)
|
||||
static void
|
||||
xfrp_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
|
||||
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
|
||||
debug(LOG_DEBUG, "working connection closed");
|
||||
debug(LOG_DEBUG, "working connection closed!");
|
||||
if (partner) {
|
||||
/* Flush all pending data */
|
||||
xfrp_read_cb(bev, ctx);
|
||||
xfrp_read_cb(bev, p);
|
||||
|
||||
if (evbuffer_get_length(bufferevent_get_output(partner))) {
|
||||
/* We still have to flush data from the other
|
||||
@@ -134,42 +138,41 @@ xfrp_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
/* We have nothing left to say to the other
|
||||
* side; close it. */
|
||||
bufferevent_free(partner);
|
||||
free_proxy(p);
|
||||
}
|
||||
}
|
||||
bufferevent_free(bev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xfrp_decrypt_cb(struct bufferevent *bev, void *ctx)
|
||||
int is_ftp_proxy(const struct proxy_service *ps)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
struct evbuffer *src, *dst;
|
||||
src = bufferevent_get_input(bev);
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
}
|
||||
if (! ps || ! ps->proxy_type)
|
||||
return 0;
|
||||
|
||||
static void
|
||||
xfrp_encrypt_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct bufferevent *partner = ctx;
|
||||
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);
|
||||
}
|
||||
if (0 == strcmp(ps->proxy_type, "ftp") && ps->remote_data_port > 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// create frp tunnel for service
|
||||
void start_frp_tunnel(struct proxy_client *client)
|
||||
void start_xfrp_tunnel(struct proxy_client *client)
|
||||
{
|
||||
if (! client->ctl_bev) {
|
||||
debug(LOG_ERR, "proxy client control bev is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
struct event_base *base = client->base;
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
struct proxy_service *ps = client->ps;
|
||||
|
||||
if (! base) {
|
||||
debug(LOG_ERR, "service event base get failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (! ps) {
|
||||
debug(LOG_ERR, "service tunnel started failed, no proxy service resource.");
|
||||
return;
|
||||
@@ -189,21 +192,34 @@ void start_frp_tunnel(struct proxy_client *client)
|
||||
|
||||
debug(LOG_DEBUG, "proxy server [%s:%d] <---> client [%s:%d]",
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port,
|
||||
ps->remote_port,
|
||||
ps->local_ip ? ps->local_ip:"::1",
|
||||
ps->local_port);
|
||||
|
||||
struct proxy *ctl_prox = new_proxy_buf(client->ctl_bev);
|
||||
struct proxy *local_prox = new_proxy_buf(client->local_proxy_bev);
|
||||
bufferevent_data_cb proxy_s2c_cb, proxy_c2s_cb;
|
||||
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);
|
||||
} else {
|
||||
proxy_c2s_cb = tcp_proxy_c2s_cb;
|
||||
proxy_s2c_cb = tcp_proxy_s2c_cb;
|
||||
}
|
||||
|
||||
bufferevent_setcb(client->ctl_bev,
|
||||
xfrp_decrypt_cb,
|
||||
proxy_s2c_cb,
|
||||
NULL,
|
||||
xfrp_event_cb,
|
||||
client->local_proxy_bev);
|
||||
local_prox);
|
||||
|
||||
bufferevent_setcb(client->local_proxy_bev,
|
||||
xfrp_encrypt_cb,
|
||||
proxy_c2s_cb,
|
||||
NULL,
|
||||
xfrp_event_cb,
|
||||
client->ctl_bev);
|
||||
ctl_prox);
|
||||
|
||||
bufferevent_enable(client->ctl_bev, EV_READ|EV_WRITE);
|
||||
bufferevent_enable(client->local_proxy_bev, EV_READ|EV_WRITE);
|
||||
@@ -221,9 +237,7 @@ int send_client_data_tail(struct proxy_client *client)
|
||||
|
||||
void free_proxy_client(struct proxy_client *client)
|
||||
{
|
||||
if (client->name) free(client->name);
|
||||
if (client->local_ip) free(client->local_ip);
|
||||
if (client->locations) free(client->locations);
|
||||
|
||||
free_base_config(client->bconf);
|
||||
|
||||
@@ -250,4 +264,11 @@ struct proxy_service *get_proxy_service(const char *proxy_name)
|
||||
struct proxy_service *all_ps = get_all_proxy_services();
|
||||
HASH_FIND_STR(all_ps, proxy_name, ps);
|
||||
return ps;
|
||||
}
|
||||
|
||||
struct proxy_client *new_proxy_client()
|
||||
{
|
||||
struct proxy_client *client = calloc(1, sizeof(struct proxy_client));
|
||||
assert(client);
|
||||
return client;
|
||||
}
|
||||
9
client.h
9
client.h
@@ -45,14 +45,10 @@ struct proxy_client {
|
||||
struct event *ev_timeout;
|
||||
|
||||
struct base_conf *bconf;
|
||||
char *name; // pointer to bconf->name
|
||||
char *local_ip;
|
||||
char *type;
|
||||
int local_port;
|
||||
int remote_port;
|
||||
|
||||
char *subdomain;
|
||||
char *locations;
|
||||
char *host_header_rewrite;
|
||||
|
||||
//provate arguments
|
||||
@@ -92,7 +88,7 @@ struct proxy_service {
|
||||
// when xfrp client receive that request, it will start
|
||||
// frp tunnel
|
||||
// if client has data-tail(not NULL), client value will be changed
|
||||
void start_frp_tunnel(struct proxy_client *client);
|
||||
void start_xfrp_tunnel(struct proxy_client *client);
|
||||
|
||||
void del_proxy_client(struct proxy_client *client);
|
||||
|
||||
@@ -102,4 +98,7 @@ struct proxy_service *get_proxy_service(const char *proxy_name);
|
||||
|
||||
int send_client_data_tail(struct proxy_client *client);
|
||||
|
||||
int is_ftp_proxy(const struct proxy_service *ps);
|
||||
struct proxy_client *new_proxy_client();
|
||||
|
||||
#endif //_CLIENT_H_
|
||||
|
||||
59
config.c
59
config.c
@@ -38,12 +38,14 @@
|
||||
#include "client.h"
|
||||
#include "debug.h"
|
||||
#include "msg.h"
|
||||
#include "utils.h"
|
||||
#include "version.h"
|
||||
|
||||
static struct common_conf *c_conf;
|
||||
static struct proxy_client *p_clients;
|
||||
static struct proxy_service *p_services;
|
||||
|
||||
static void new_ftp_data_proxy_service(struct proxy_service *ftp_ps);
|
||||
|
||||
struct common_conf *get_common_config()
|
||||
{
|
||||
@@ -135,8 +137,17 @@ static void dump_proxy_service(const int index, struct proxy_service *ps)
|
||||
} else if (strcmp(ps->proxy_type, "ftp") == 0) {
|
||||
if (ps->remote_data_port <= 0) {
|
||||
debug(LOG_ERR,
|
||||
"Proxy [%s] error: remote_data_port must be exist when type is ftp");
|
||||
"Proxy [%s] error: remote_data_port must be exist when type is ftp",
|
||||
ps->proxy_name);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!is_valid_ip_address((const char *)c_conf->server_addr)){
|
||||
debug(LOG_ERR, "now ftp proxy only support ip address in [server_addr]");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
new_ftp_data_proxy_service(ps);
|
||||
}
|
||||
|
||||
debug(LOG_DEBUG,
|
||||
@@ -187,6 +198,32 @@ static struct proxy_service *new_proxy_service(const char *name)
|
||||
return ps;
|
||||
}
|
||||
|
||||
// create a new proxy service with suffix "_ftp_data_proxy"
|
||||
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);
|
||||
if (!ps) {
|
||||
ps = new_proxy_service(ftp_data_proxy_name);
|
||||
if (! ps) {
|
||||
debug(LOG_ERR,
|
||||
"cannot create ftp data proxy service, it should not happenned!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
ps->proxy_type = strdup("tcp");
|
||||
ps->remote_port = ftp_ps->remote_data_port;
|
||||
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);
|
||||
}
|
||||
|
||||
free(ftp_data_proxy_name);
|
||||
}
|
||||
|
||||
static int
|
||||
proxy_service_handler(void *user, const char *sect, const char *nm, const char *value)
|
||||
{
|
||||
@@ -232,6 +269,8 @@ proxy_service_handler(void *user, const char *sect, const char *nm, const char *
|
||||
ps->use_encryption = is_true(value);
|
||||
} else if (MATCH_NAME("remote_port")) {
|
||||
ps->remote_port = atoi(value);
|
||||
} else if (MATCH_NAME("remote_data_port")) {
|
||||
ps->remote_data_port = atoi(value);
|
||||
} else if (MATCH_NAME("http_user")) {
|
||||
ps->http_user = strdup(value);
|
||||
assert(ps->http_user);
|
||||
@@ -332,6 +371,24 @@ static void init_common_conf(struct common_conf *config)
|
||||
config->user = NULL;
|
||||
}
|
||||
|
||||
// it should be free after using
|
||||
// because of assert it will never return NULL
|
||||
char *get_ftp_data_proxy_name(const char *ftp_proxy_name)
|
||||
{
|
||||
char *ftp_tail_data_name = FTP_DATA_PROXY_SUFFIX;
|
||||
char *ftp_data_proxy_name = (char *)calloc(1,
|
||||
strlen(ftp_proxy_name)+strlen(ftp_tail_data_name)+1);
|
||||
assert(ftp_data_proxy_name);
|
||||
|
||||
snprintf(ftp_data_proxy_name,
|
||||
strlen(ftp_proxy_name) + strlen(ftp_tail_data_name) + 1,
|
||||
"%s%s",
|
||||
ftp_proxy_name,
|
||||
ftp_tail_data_name);
|
||||
|
||||
return ftp_data_proxy_name;
|
||||
}
|
||||
|
||||
void load_config(const char *confile)
|
||||
{
|
||||
c_conf = (struct common_conf *)calloc(sizeof(struct common_conf), 1);
|
||||
|
||||
3
config.h
3
config.h
@@ -29,6 +29,8 @@
|
||||
#include "client.h"
|
||||
#include "common.h"
|
||||
|
||||
#define FTP_DATA_PROXY_SUFFIX "_ftp_data_proxy"
|
||||
|
||||
struct base_conf{
|
||||
char *name;
|
||||
char *auth_token;
|
||||
@@ -68,5 +70,6 @@ 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);
|
||||
|
||||
#endif //_CONFIG_H_
|
||||
|
||||
83
control.c
83
control.c
@@ -90,16 +90,17 @@ static int client_connected(int is_connected)
|
||||
|
||||
static int set_client_work_start(struct proxy_client *client, int is_start_work)
|
||||
{
|
||||
if (is_start_work)
|
||||
if (is_start_work) {
|
||||
assert(client->ps);
|
||||
client->work_started = 1;
|
||||
else
|
||||
}else
|
||||
client->work_started = 0;
|
||||
|
||||
return client->work_started;
|
||||
}
|
||||
|
||||
static int is_client_work_started(struct proxy_client *client) {
|
||||
return client->work_started;
|
||||
return client->work_started && client->ps;
|
||||
}
|
||||
|
||||
static void client_start_event_cb(struct bufferevent *bev, short what, void *ctx)
|
||||
@@ -121,14 +122,13 @@ static void client_start_event_cb(struct bufferevent *bev, short what, void *ctx
|
||||
bufferevent_setcb(bev, recv_cb, NULL, client_start_event_cb, client);
|
||||
bufferevent_enable(bev, EV_READ|EV_WRITE);
|
||||
sync_new_work_connection(bev);
|
||||
debug(LOG_INFO, "proxy service connected");
|
||||
debug(LOG_INFO, "proxy service start");
|
||||
}
|
||||
}
|
||||
|
||||
static void new_client_connect()
|
||||
{
|
||||
struct proxy_client *client = calloc(1, sizeof(struct proxy_client)); //NEED FREE
|
||||
assert(client);
|
||||
struct proxy_client *client = new_proxy_client();
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
assert(c_conf);
|
||||
client->base = main_ctl->connect_base;;
|
||||
@@ -213,25 +213,6 @@ REQ_END:
|
||||
return write_len;
|
||||
}
|
||||
|
||||
void control_request_free(struct control_request *req)
|
||||
{
|
||||
if (!req)
|
||||
return;
|
||||
|
||||
if (req->proxy_name) free(req->proxy_name);
|
||||
if (req->auth_key) free(req->auth_key);
|
||||
if (req->privilege_key) free(req->privilege_key);
|
||||
if (req->proxy_type) free(req->proxy_type);
|
||||
if (req->custom_domains) free(req->custom_domains);
|
||||
if (req->locations) free(req->locations);
|
||||
if (req->host_header_rewrite) free(req->host_header_rewrite);
|
||||
if (req->http_username) free(req->http_username);
|
||||
if (req->http_password) free(req->http_password);
|
||||
if (req->subdomain) free(req->subdomain);
|
||||
|
||||
free(req);
|
||||
}
|
||||
|
||||
static void base_control_ping(struct bufferevent *bev) {
|
||||
if ( ! is_client_connected())
|
||||
return;
|
||||
@@ -388,7 +369,7 @@ raw_message(struct message *msg, struct bufferevent *bev, struct proxy_client *c
|
||||
{
|
||||
if (client) {
|
||||
if (client->work_started) {
|
||||
debug(LOG_DEBUG, "raw client [%s] control message.", client->name);
|
||||
debug(LOG_DEBUG, "raw client [%s] control message.", client->ps->proxy_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,14 +435,13 @@ raw_message(struct message *msg, struct bufferevent *bev, struct proxy_client *c
|
||||
}
|
||||
|
||||
client->ps = ps;
|
||||
client->name = ps->proxy_name;
|
||||
debug(LOG_INFO,
|
||||
"proxy service [%s] [%s:%d] start work connection.",
|
||||
sr->proxy_name,
|
||||
ps->local_ip,
|
||||
ps->local_port);
|
||||
|
||||
start_frp_tunnel(client);
|
||||
start_xfrp_tunnel(client);
|
||||
set_client_work_start(client, 1);
|
||||
break;
|
||||
case TypePong:
|
||||
@@ -477,7 +457,8 @@ static size_t data_handler(unsigned char *buf, ushort len, struct proxy_client *
|
||||
{
|
||||
struct bufferevent *bev = NULL;
|
||||
if (client) {
|
||||
debug(LOG_DEBUG, "client [name:%s] recved control data", client->name);
|
||||
debug(LOG_DEBUG, "client(%s): recved control data",
|
||||
is_client_work_started(client)?"work":"free");
|
||||
bev = client->ctl_bev;
|
||||
}
|
||||
unsigned char *ret_buf = NULL;
|
||||
@@ -635,7 +616,7 @@ static unsigned char
|
||||
if (is_client_work_started(client)) {
|
||||
debug(LOG_DEBUG,
|
||||
"client [%s] send all work data to proxy tunnel.",
|
||||
client->name);
|
||||
client->ps->proxy_name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -739,7 +720,7 @@ static void recv_cb(struct bufferevent *bev, void *ctx)
|
||||
for(i = 0; i<read_n && ((2 * i) < (read_n * 2 + 1)); i++) {
|
||||
snprintf(dbg_buf + 4*i, 5, "%3u ", (unsigned char)raw_buf_p[i]);
|
||||
}
|
||||
debug(LOG_DEBUG, "[%s]: RECV ctl byte:%s", client ? "client":"control", dbg_buf);
|
||||
debug(LOG_DEBUG, "[%s]: RECV ctl byte:%s", client?"client":"control", dbg_buf);
|
||||
SAFE_FREE(dbg_buf);
|
||||
#endif //CONN_DEBUG
|
||||
|
||||
@@ -781,7 +762,16 @@ static void open_connection_session(struct bufferevent *bev)
|
||||
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;
|
||||
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
|
||||
if (retry_times >= 10) {
|
||||
debug(LOG_INFO,
|
||||
"have retry connect to xfrp server for %d times, exit!",
|
||||
retry_times);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
retry_times++;
|
||||
debug(LOG_ERR, "connect server [%s:%d] failed",
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port);
|
||||
@@ -790,6 +780,7 @@ static void connect_event_cb (struct bufferevent *bev, short what, void *ctx)
|
||||
start_base_connect();
|
||||
close_main_control();
|
||||
} else if (what & BEV_EVENT_CONNECTED) {
|
||||
retry_times = 0;
|
||||
// recv login-response message before recving othfer fprs messages,
|
||||
bufferevent_setcb(bev, recv_cb, NULL, connect_event_cb, NULL);
|
||||
bufferevent_enable(bev, EV_READ|EV_WRITE|EV_PERSIST);
|
||||
@@ -820,7 +811,10 @@ void start_base_connect()
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port);
|
||||
if ( ! main_ctl->connect_bev) {
|
||||
debug(LOG_ERR, "Connect server [%s:%d] failed", c_conf->server_addr, c_conf->server_port);
|
||||
debug(LOG_ERR,
|
||||
"Connect server [%s:%d] failed",
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -899,7 +893,9 @@ void send_msg_frp_server(struct bufferevent *bev,
|
||||
|
||||
char frame_type = 0;
|
||||
struct frame *f = NULL;
|
||||
f = new_frame(frame_type, sid); // frame_type not truely matter, it will reset by set_frame_cmd
|
||||
|
||||
// frame_type not truely matter, it will reset by set_frame_cmd
|
||||
f = new_frame(frame_type, sid);
|
||||
assert(f);
|
||||
|
||||
if (msg) {
|
||||
@@ -907,9 +903,9 @@ void send_msg_frp_server(struct bufferevent *bev,
|
||||
assert(req_msg.data_p);
|
||||
}
|
||||
|
||||
unsigned char *puck_buf = NULL;
|
||||
size_t pack_buf_len = pack(&req_msg, &puck_buf);
|
||||
if ( ! pack_buf_len || ! puck_buf) {
|
||||
unsigned char *pack_buf = NULL;
|
||||
size_t pack_buf_len = pack(&req_msg, &pack_buf);
|
||||
if ( ! pack_buf_len || ! pack_buf) {
|
||||
debug(LOG_ERR, "send buffer pack failed!");
|
||||
goto S_M_F_END;
|
||||
}
|
||||
@@ -922,7 +918,7 @@ void send_msg_frp_server(struct bufferevent *bev,
|
||||
struct frp_coder *encoder = get_main_encoder();
|
||||
|
||||
if (encoder) {
|
||||
size_t encode_ret_len = encrypt_data(puck_buf, pack_buf_len, encoder, &encode_ret);
|
||||
size_t encode_ret_len = encrypt_data(pack_buf, pack_buf_len, encoder, &encode_ret);
|
||||
debug(LOG_DEBUG, "encode len:[%lu]", encode_ret_len);
|
||||
|
||||
if (encode_ret_len > 0) {
|
||||
@@ -936,7 +932,7 @@ void send_msg_frp_server(struct bufferevent *bev,
|
||||
#endif //ENCRYPTO
|
||||
if (! f->data) {
|
||||
set_frame_len(f, (ushort) pack_buf_len);
|
||||
f->data = puck_buf;
|
||||
f->data = pack_buf;
|
||||
}
|
||||
|
||||
if (get_common_config()->tcp_mux) {
|
||||
@@ -973,13 +969,18 @@ struct control *get_main_control()
|
||||
void start_login_frp_server(struct event_base *base)
|
||||
{
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
struct bufferevent *bev = connect_server(base, c_conf->server_addr, c_conf->server_port);
|
||||
struct bufferevent *bev = connect_server(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);
|
||||
debug(LOG_DEBUG,
|
||||
"Connect server [%s:%d] failed",
|
||||
c_conf->server_addr,
|
||||
c_conf->server_port);
|
||||
return;
|
||||
}
|
||||
|
||||
debug(LOG_INFO, "Xfrpc login: connect server [%s:%d] ......", c_conf->server_addr, c_conf->server_port);
|
||||
debug(LOG_INFO, "Xfrpc login: connect server [%s:%d] ...", c_conf->server_addr, c_conf->server_port);
|
||||
|
||||
bufferevent_enable(bev, EV_WRITE|EV_READ);
|
||||
bufferevent_setcb(bev, NULL, NULL, connect_event_cb, NULL);
|
||||
|
||||
@@ -70,6 +70,4 @@ void send_new_proxy(struct proxy_service *ps);
|
||||
struct bufferevent
|
||||
*connect_server(struct event_base *base, const char *name, const int port);
|
||||
|
||||
void control_request_free(struct control_request *req);
|
||||
|
||||
#endif //_CONTROL_H_
|
||||
5
msg.c
5
msg.c
@@ -41,6 +41,7 @@
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
#include "login.h"
|
||||
#include "client.h"
|
||||
|
||||
#define JSON_MARSHAL_TYPE(jobj,key,jtype,item) \
|
||||
json_object_object_add(jobj, key, json_object_new_##jtype((item)));
|
||||
@@ -173,6 +174,10 @@ int new_proxy_service_marshal(const struct proxy_service *np_req, char **msg)
|
||||
JSON_MARSHAL_TYPE(j_np_req, "use_compression", boolean, np_req->use_compression);
|
||||
JSON_MARSHAL_TYPE(j_np_req, "remote_port", int, np_req->remote_port);
|
||||
|
||||
if (is_ftp_proxy(np_req)) {
|
||||
JSON_MARSHAL_TYPE(j_np_req, "remote_data_port", int, np_req->remote_data_port);
|
||||
}
|
||||
|
||||
if (np_req->custom_domains) {
|
||||
fill_custom_domains(j_np_req, np_req->custom_domains);
|
||||
} else {
|
||||
|
||||
24
msg.h
24
msg.h
@@ -61,29 +61,6 @@ struct general_response {
|
||||
char *msg;
|
||||
};
|
||||
|
||||
// messages between control connections of frpc and frps
|
||||
struct control_request {
|
||||
int type;
|
||||
char *proxy_name;
|
||||
char *auth_key;
|
||||
int use_encryption;
|
||||
int use_gzip;
|
||||
int pool_count;
|
||||
|
||||
int privilege_mode;
|
||||
char *privilege_key;
|
||||
char *proxy_type;
|
||||
int remote_port;
|
||||
char *custom_domains;
|
||||
char *locations;
|
||||
char *host_header_rewrite;
|
||||
char *http_username;
|
||||
char *http_password;
|
||||
char *subdomain;
|
||||
long timestamp;
|
||||
};
|
||||
|
||||
|
||||
struct control_response {
|
||||
int type;
|
||||
int code;
|
||||
@@ -114,7 +91,6 @@ size_t pack(struct message *req_msg, unsigned char **ret_buf);
|
||||
struct message *unpack(unsigned char *recv_msg, const ushort len);
|
||||
|
||||
// tranlate control request to json string
|
||||
int control_request_marshal(const struct control_request *req, char **msg);
|
||||
struct login_resp *login_resp_unmarshal(const char *jres);
|
||||
struct start_work_conn_resp *start_work_conn_resp_unmarshal(const char *resp_msg);
|
||||
|
||||
|
||||
36
proxy.c
Normal file
36
proxy.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#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"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
#include "config.h"
|
||||
|
||||
struct proxy *new_proxy_buf(struct bufferevent *bev)
|
||||
{
|
||||
struct proxy *p = (struct proxy *)calloc(1, sizeof(struct proxy));
|
||||
assert(p);
|
||||
p->bev = bev;
|
||||
p->remote_data_port = -1;
|
||||
p->proxy_name = NULL;
|
||||
return p;
|
||||
}
|
||||
|
||||
void free_proxy(struct proxy *p)
|
||||
{
|
||||
SAFE_FREE(p->proxy_name);
|
||||
SAFE_FREE(p);
|
||||
}
|
||||
37
proxy.h
Normal file
37
proxy.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef _PROXY_H_
|
||||
#define _PROXY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/util.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "common.h"
|
||||
|
||||
#define IP_LEN 16
|
||||
|
||||
struct ftp_pasv {
|
||||
int code;
|
||||
char ftp_server_ip[IP_LEN];
|
||||
int ftp_server_port;
|
||||
};
|
||||
|
||||
struct proxy {
|
||||
struct bufferevent *bev;
|
||||
char *proxy_name;
|
||||
int remote_data_port; //used in ftp proxy
|
||||
};
|
||||
|
||||
void tcp_proxy_c2s_cb(struct bufferevent *bev, void *ctx);
|
||||
void tcp_proxy_s2c_cb(struct bufferevent *bev, void *ctx);
|
||||
void ftp_proxy_c2s_cb(struct bufferevent *bev, void *ctx);
|
||||
void ftp_proxy_s2c_cb(struct bufferevent *bev, void *ctx);
|
||||
struct proxy *new_proxy_buf(struct bufferevent *bev);
|
||||
void free_proxy(struct proxy *p);
|
||||
void set_ftp_data_proxy_tunnel(const char *ftp_proxy_name,
|
||||
struct ftp_pasv *local_fp,
|
||||
struct ftp_pasv *remote_fp);
|
||||
#endif //_PROXY_H_
|
||||
258
proxy_ftp.c
Normal file
258
proxy_ftp.c
Normal file
@@ -0,0 +1,258 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#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"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
#include "config.h"
|
||||
#include "client.h"
|
||||
|
||||
#define FTP_PRO_BUF 256
|
||||
#define FTP_PASV_PORT_BLOCK 256
|
||||
|
||||
static struct ftp_pasv *new_ftp_pasv();
|
||||
static void free_ftp_pasv(struct ftp_pasv *fp);
|
||||
static struct ftp_pasv * pasv_unpack(char *data);
|
||||
static size_t pasv_pack(struct ftp_pasv *fp, char **pack_p);
|
||||
|
||||
void set_ftp_data_proxy_tunnel(const char *ftp_proxy_name,
|
||||
struct ftp_pasv *local_fp,
|
||||
struct ftp_pasv *remote_fp)
|
||||
{
|
||||
struct proxy_service *ps = NULL;
|
||||
char *ftp_data_proxy_name = get_ftp_data_proxy_name(ftp_proxy_name);
|
||||
|
||||
struct proxy_service *p_services = get_all_proxy_services();
|
||||
HASH_FIND_STR(p_services, ftp_data_proxy_name, ps);
|
||||
if (!ps) {
|
||||
debug(LOG_ERR,
|
||||
"error: ftp data proxy not inserted in proxy-service queue, it should not happend!");
|
||||
goto FTP_DATA_PROXY_TUNNEL_END;
|
||||
}
|
||||
|
||||
ps->local_port = local_fp->ftp_server_port;
|
||||
ps->local_ip = strdup(local_fp->ftp_server_ip);
|
||||
assert(ps->local_ip);
|
||||
|
||||
ps->remote_port = remote_fp->ftp_server_port;
|
||||
|
||||
debug(LOG_DEBUG,
|
||||
"set ftp proxy DATA port [local:remote] = [%d:%d]",
|
||||
ps->local_port, ps->remote_port);
|
||||
|
||||
FTP_DATA_PROXY_TUNNEL_END:
|
||||
free(ftp_data_proxy_name);
|
||||
}
|
||||
|
||||
// read from client-working host port
|
||||
void ftp_proxy_c2s_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
assert(p);
|
||||
struct bufferevent *partner = p->bev;
|
||||
|
||||
struct evbuffer *src, *dst;
|
||||
size_t len;
|
||||
src = bufferevent_get_input(bev);
|
||||
len = evbuffer_get_length(src);
|
||||
if (len < 0)
|
||||
return;
|
||||
|
||||
dst = bufferevent_get_output(partner);
|
||||
assert(dst);
|
||||
|
||||
unsigned char *buf = calloc(1, len);
|
||||
assert(buf);
|
||||
size_t read_n = 0;
|
||||
read_n = evbuffer_remove(src, buf, len);
|
||||
|
||||
// #define FTP_P_DEBUG 1
|
||||
#ifdef FTP_P_DEBUG
|
||||
char *dbg_buf = calloc(1, read_n * 7 + 1);
|
||||
assert(dbg_buf);
|
||||
unsigned int i = 0;
|
||||
for(i = 0; i<read_n && ((2 * i) < (read_n * 2 + 1)); i++) {
|
||||
snprintf(dbg_buf + 7*i, 8, "%3u[%c] ",
|
||||
(unsigned char)buf[i],
|
||||
(unsigned char)buf[i]);
|
||||
}
|
||||
debug(LOG_DEBUG, "FTP Client RECV ctl byte:%s", dbg_buf);
|
||||
debug(LOG_DEBUG, "FTP Client RECV ctl stri:%s", buf);
|
||||
SAFE_FREE(dbg_buf);
|
||||
#endif //FTP_P_DEBUG
|
||||
|
||||
struct ftp_pasv *local_fp = pasv_unpack((char *)buf);
|
||||
|
||||
if (local_fp) {
|
||||
struct common_conf *c_conf = get_common_config();
|
||||
struct ftp_pasv *r_fp = new_ftp_pasv();
|
||||
r_fp->code = local_fp->code;
|
||||
|
||||
strncpy(r_fp->ftp_server_ip, c_conf->server_addr, IP_LEN);
|
||||
r_fp->ftp_server_port = p->remote_data_port;
|
||||
|
||||
if (r_fp->ftp_server_port <= 0) {
|
||||
debug(LOG_ERR, "error: remote ftp data port is not init!");
|
||||
goto FTP_C2S_CB_END;
|
||||
}
|
||||
|
||||
char *pasv_msg = NULL;
|
||||
size_t pack_len = pasv_pack(r_fp, &pasv_msg);
|
||||
if ( ! pack_len){
|
||||
debug(LOG_ERR, "error: ftp proxy replace failed!");
|
||||
SAFE_FREE(pasv_msg);
|
||||
goto FTP_C2S_CB_END;
|
||||
}
|
||||
|
||||
set_ftp_data_proxy_tunnel(p->proxy_name, local_fp, r_fp);
|
||||
evbuffer_add(dst, pasv_msg, pack_len);
|
||||
SAFE_FREE(pasv_msg);
|
||||
} else {
|
||||
evbuffer_add(dst, buf, read_n);
|
||||
}
|
||||
|
||||
FTP_C2S_CB_END:
|
||||
SAFE_FREE(buf);
|
||||
free_ftp_pasv(local_fp);
|
||||
return;
|
||||
}
|
||||
|
||||
void ftp_proxy_s2c_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
tcp_proxy_s2c_cb(bev, ctx);
|
||||
}
|
||||
|
||||
static struct ftp_pasv *pasv_unpack(char *data)
|
||||
{
|
||||
char cd_buf[4] = {0};
|
||||
snprintf(cd_buf, 4, "%s", data);
|
||||
int code = atoi(cd_buf);
|
||||
if (code != 227 && code != 211 && code != 229)
|
||||
return NULL;
|
||||
|
||||
struct ftp_pasv *fp = new_ftp_pasv();
|
||||
assert(fp);
|
||||
|
||||
fp->code = code;
|
||||
switch(fp->code) {
|
||||
case 227:
|
||||
{
|
||||
int i = 0, ip_i = 0, port_i = 0, ip_start = 0, comma_n = 0;
|
||||
char port[2][4] = { {0}, {0} };
|
||||
for (i=0; i<strlen(data) && ip_i<IP_LEN; i++) {
|
||||
if (data[i] == '(') {
|
||||
ip_start = 1;
|
||||
continue;
|
||||
}
|
||||
if (! ip_start)
|
||||
continue;
|
||||
|
||||
if (data[i] == ')')
|
||||
break;
|
||||
|
||||
if (data[i] == ','){
|
||||
comma_n++;
|
||||
port_i = 0;
|
||||
if (comma_n < 4){
|
||||
fp->ftp_server_ip[ip_i] = '.';
|
||||
ip_i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (comma_n >= 4 && port_i < 4) {
|
||||
port[comma_n - 4][port_i] = data[i];
|
||||
port_i++;
|
||||
continue;
|
||||
}
|
||||
fp->ftp_server_ip[ip_i] = data[i];
|
||||
ip_i++;
|
||||
}
|
||||
|
||||
fp->ftp_server_port = atoi(port[0]) * FTP_PASV_PORT_BLOCK + atoi(port[1]);
|
||||
debug(LOG_DEBUG, "ftp pasv unpack:[%s:%d]", fp->ftp_server_ip, fp->ftp_server_port);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
free_ftp_pasv(fp);
|
||||
break;
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
// the value returned need FREE after using
|
||||
static size_t pasv_pack(struct ftp_pasv *fp, char **pack_p)
|
||||
{
|
||||
*pack_p = (char *)calloc(1, FTP_PRO_BUF);
|
||||
assert(*pack_p);
|
||||
size_t pack_len = 0;
|
||||
|
||||
switch (fp->code){
|
||||
case 227:
|
||||
{
|
||||
char ftp_ip[IP_LEN] = {0};
|
||||
int i =0;
|
||||
for (i=0; i<strlen(fp->ftp_server_ip) && i < IP_LEN; i++) {
|
||||
if (fp->ftp_server_ip[i] == '.') {
|
||||
ftp_ip[i] = ',';
|
||||
continue;
|
||||
}
|
||||
|
||||
ftp_ip[i] = fp->ftp_server_ip[i];
|
||||
}
|
||||
snprintf(*pack_p,
|
||||
FTP_PRO_BUF,
|
||||
"227 Entering Passive Mode (%s,%d,%d).\n",
|
||||
ftp_ip,
|
||||
fp->ftp_server_port / FTP_PASV_PORT_BLOCK,
|
||||
fp->ftp_server_port % FTP_PASV_PORT_BLOCK);
|
||||
|
||||
pack_len = strlen(*pack_p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
debug(LOG_DEBUG, "ftp pasv protocol data not supportted in pasv_pack");
|
||||
free(*pack_p);
|
||||
break;
|
||||
}
|
||||
|
||||
return pack_len;
|
||||
}
|
||||
|
||||
// need be free after using
|
||||
static struct ftp_pasv *new_ftp_pasv()
|
||||
{
|
||||
struct ftp_pasv *fp = (struct ftp_pasv *)calloc(1, sizeof(struct ftp_pasv));
|
||||
if (! fp)
|
||||
return NULL;
|
||||
|
||||
memset(fp->ftp_server_ip, 0, IP_LEN);
|
||||
fp->ftp_server_port = -1;
|
||||
fp->code = -1;
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
// can be used to free NULL pointer also
|
||||
static void free_ftp_pasv(struct ftp_pasv *fp)
|
||||
{
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
SAFE_FREE(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
44
proxy_tcp.c
Normal file
44
proxy_tcp.c
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#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"
|
||||
#include "common.h"
|
||||
#include "proxy.h"
|
||||
|
||||
// read from client-working host port
|
||||
void tcp_proxy_c2s_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_proxy_s2c_cb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct proxy *p = (struct proxy *)ctx;
|
||||
struct bufferevent *partner = p?p->bev:NULL;
|
||||
struct evbuffer *src, *dst;
|
||||
src = bufferevent_get_input(bev);
|
||||
dst = bufferevent_get_output(partner);
|
||||
evbuffer_add_buffer(dst, src);
|
||||
}
|
||||
9
utils.c
9
utils.c
@@ -20,3 +20,12 @@ void s_sleep(unsigned int s, unsigned int u)
|
||||
timeout.tv_usec = u;
|
||||
select(0, NULL, NULL, NULL, &timeout);
|
||||
}
|
||||
|
||||
// is_valid_ip_address:
|
||||
// return 0:ipaddress unlegal
|
||||
int is_valid_ip_address(const char *ip_address)
|
||||
{
|
||||
struct sockaddr_in sa;
|
||||
int result = inet_pton(AF_INET, ip_address, &(sa.sin_addr));
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user