From ca649052668857ec99b123bf7df7957603dd6fb3 Mon Sep 17 00:00:00 2001 From: Dengfeng Liu Date: Sun, 29 May 2022 12:25:56 +0800 Subject: [PATCH] fix: process unhandle tcp mux header Signed-off-by: Dengfeng Liu --- client.c | 12 +++++--- client.h | 2 ++ control.c | 1 - systemd/xfrpc.service | 16 ++++++++++ tcpmux.c | 71 ++++++++++++++++++++++++++++--------------- tcpmux.h | 25 ++++++++------- version.h | 2 +- 7 files changed, 85 insertions(+), 44 deletions(-) create mode 100644 systemd/xfrpc.service diff --git a/client.c b/client.c index a7f3e15..daec81a 100644 --- a/client.c +++ b/client.c @@ -70,8 +70,11 @@ xfrp_proxy_event_cb(struct bufferevent *bev, short what, void *ctx) 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_rst(client->ctl_bev, client->stream_id); - } else if (what & BEV_EVENT_CONNECTED) { + 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); @@ -122,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; } @@ -183,7 +186,7 @@ void del_proxy_client(struct proxy_client *client) { if (!client || !all_pc ) { - debug(LOG_INFO, "Error: all_pc or client is NULL"); + debug(LOG_INFO, "all_pc or client is NULL"); return; } @@ -207,6 +210,7 @@ new_proxy_client() assert(client); client->stream_id = get_next_session_id(); client->send_window = 128*1024; + client->stream_state = INIT; HASH_ADD_INT(all_pc, stream_id, client); return client; diff --git a/client.h b/client.h index 852b701..503b2e0 100644 --- a/client.h +++ b/client.h @@ -31,6 +31,7 @@ #include "uthash.h" #include "common.h" +#include "tcpmux.h" struct event_base; struct base_conf; @@ -46,6 +47,7 @@ struct proxy_client { uint32_t stream_id; uint32_t send_window; + enum tcp_mux_state stream_state; int connected; int work_started; struct proxy_service *ps; diff --git a/control.c b/control.c index f66622b..9642a1f 100644 --- a/control.c +++ b/control.c @@ -526,7 +526,6 @@ connect_event_cb (struct bufferevent *bev, short what, void *ctx) strerror(errno)); clear_main_control(); start_base_connect(); - exit(0); } else if (what & BEV_EVENT_CONNECTED) { retry_times = 0; diff --git a/systemd/xfrpc.service b/systemd/xfrpc.service new file mode 100644 index 0000000..d5580cf --- /dev/null +++ b/systemd/xfrpc.service @@ -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 diff --git a/tcpmux.c b/tcpmux.c index 87c979b..cbd16cd 100644 --- a/tcpmux.c +++ b/tcpmux.c @@ -66,8 +66,8 @@ flag_2_desc(enum tcp_mux_flag flag) if (flag == flag_desc[i].flag) return flag_desc[i].desc; } - - return "unknown_flag"; + + return "unkown_flag"; } static int @@ -79,15 +79,6 @@ valid_tcp_mux_type(uint8_t type) return 0; } -static int -valid_tcp_mux_flag(uint16_t flag) -{ - if (flag >= ZERO && flag <= RST) - return 1; - - return 0; -} - static int valid_tcp_mux_sid(uint32_t sid) { @@ -140,8 +131,7 @@ parse_tcp_mux_proto(uint8_t *data, int len, uint32_t *flag, uint32_t *type, uint struct tcp_mux_header *hdr = (struct tcp_mux_header *)data; if(hdr->version == proto_version && - valid_tcp_mux_type(hdr->type) && - valid_tcp_mux_flag(htons(hdr->flags))) { + 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)); @@ -191,14 +181,14 @@ tcp_mux_send_win_update_ack(struct bufferevent *bout, uint32_t stream_id, uint32 } void -tcp_mux_send_win_update_rst(struct bufferevent *bout, uint32_t stream_id) +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, RST, stream_id, 0, &tmux_hdr); - debug(LOG_DEBUG, "tcp mux [%d] send wind update RST", stream_id); + 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)); } @@ -266,7 +256,15 @@ handle_tcp_mux_frps_msg(uint8_t *buf, int ilen, void (*fn)(uint8_t *, int, void data += l_dlen; ilen -= l_dlen; l_dlen = 0; - } else if ( ilen >= l_dlen) { + 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; @@ -306,12 +304,22 @@ handle_tcp_mux_frps_msg(uint8_t *buf, int ilen, void (*fn)(uint8_t *, int, void data += dlen; ilen -= dlen; l_dlen = 0; - } else if ( ilen >= dlen){ + 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; @@ -329,14 +337,27 @@ handle_tcp_mux_frps_msg(uint8_t *buf, int ilen, void (*fn)(uint8_t *, int, void } case WINDOW_UPDATE: { - if (flag == RST) { - del_proxy_client(pc); - } else if (pc && dlen > 0){ - pc->send_window += dlen; - bufferevent_enable(pc->local_proxy_bev, EV_READ|EV_WRITE); - } else { - debug(LOG_INFO, "window update no need process : flag %s dlen %d", flag_2_desc(flag), dlen); + 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: diff --git a/tcpmux.h b/tcpmux.h index c7ed402..09234d0 100644 --- a/tcpmux.h +++ b/tcpmux.h @@ -44,9 +44,17 @@ struct tcp_mux_type_desc { enum tcp_mux_flag { ZERO, SYN, - ACK, - FIN, - RST, + 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 { @@ -65,20 +73,11 @@ enum tcp_mux_state { RESET }; - -struct __attribute__((__packed__)) tcp_mux_header { - uint8_t version; - uint8_t type; - uint16_t flags; - uint32_t stream_id; - uint32_t length; -}; - 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_rst(struct bufferevent *bout, uint32_t stream_id); +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); diff --git a/version.h b/version.h index e5b31de..60b48c5 100644 --- a/version.h +++ b/version.h @@ -1,7 +1,7 @@ #ifndef _VERSION_H_ #define _VERSION_H_ -#define VERSION "1.05.556" +#define VERSION "1.05.561" #define PROTOCOL_VERESION "0.42.0" #define CLIENT_V 1