From cef3586733e43de08f9d384f871707dfc2b41d21 Mon Sep 17 00:00:00 2001 From: Blaok Date: Fri, 24 Oct 2014 11:30:10 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E5=B0=86ss-redir?= =?UTF-8?q?=E7=9A=84=E8=BD=AC=E5=8F=91=E6=94=B9=E4=B8=BAIPv6=E8=BD=AC?= =?UTF-8?q?=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 目前`IP6T_SO_ORIGINAL_DST`这个东西上边,不能正确获取原始目标地址。尝试`curl bt.byr.cn`,前面一部分地址可以看到是`a:50::2001:da8:215:4078`,但是格式完全不对,内容也不全,正确的地址应该是`2001:da8:215:4078:250:56ff:fe97:654d`。估计是某些针对IPv4的设定没有改过来。改日再看。 另外吐槽一下原版毫无注释的代码…… --- src/redir.c | 32 +++++++++++++++++++++++--------- src/redir.h | 2 +- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/redir.c b/src/redir.c index aad0bf0e..67ad39b2 100644 --- a/src/redir.c +++ b/src/redir.c @@ -37,7 +37,9 @@ #include #include #include +#include #include +#include #ifdef HAVE_CONFIG_H #include "config.h" @@ -58,16 +60,16 @@ #define BUF_SIZE 2048 #endif -int getdestaddr(int fd, struct sockaddr_in *destaddr) +int getdestaddr( struct listen_ctx * listener, struct sockaddr_in *destaddr) { - socklen_t socklen = sizeof(*destaddr); - int error; +/* socklen_t socklen = sizeof(*destaddr); + int error=0; - error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, destaddr, &socklen); + // error = getsockopt(listener->fd, (listener->local.isIPv6()?SOL_IP6:SOL_IP), (listener->local.isIPv6()?IP6T_SO_ORIGINAL_DST:SO_ORIGINAL_DST), destaddr, &socklen); if (error) { return -1; - } + }*/ return 0; } @@ -104,6 +106,7 @@ int create_and_bind(const char *addr, const char *port) int opt = 1; setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); +// setsockopt(listen_sock, IPPROTO_IPV6, SO_REUSEADDR, &opt, sizeof(opt)); setsockopt(listen_sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); @@ -398,9 +401,9 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) // handle IP V4 only size_t in_addr_len = sizeof(struct in_addr); - memcpy(ss_addr_to_send + addr_len, &server->destaddr.sin_addr, in_addr_len); + memcpy(ss_addr_to_send + addr_len, &server->destaddr.sin6_addr, in_addr_len); addr_len += in_addr_len; - memcpy(ss_addr_to_send + addr_len, &server->destaddr.sin_port, 2); + memcpy(ss_addr_to_send + addr_len, &server->destaddr.sin6_port, 2); addr_len += 2; ss_addr_to_send = ss_encrypt(BUF_SIZE, ss_addr_to_send, &addr_len, server->e_ctx); if (ss_addr_to_send == NULL) @@ -612,7 +615,7 @@ void close_and_free_server(EV_P_ struct server *server) static void accept_cb (EV_P_ ev_io *w, int revents) { struct listen_ctx *listener = (struct listen_ctx *)w; - struct sockaddr_in destaddr; + struct sockaddr_in6 destaddr; int err; int clientfd = accept(listener->fd, NULL, NULL); @@ -622,7 +625,18 @@ static void accept_cb (EV_P_ ev_io *w, int revents) return; } - err = getdestaddr(clientfd, &destaddr); + //err = getdestaddr(listener, &destaddr); + printf("Connet server %s, port %s.\n",listener->remote_addr->host,listener->remote_addr->port); + printf("%d %s\n",listener->sock.sa_family,listener->sock.sa_data); + socklen_t socklen = sizeof(destaddr); + //err = getsockopt(listener->fd, (listener->local.isIPv6()?SOL_IP6:SOL_IP), (listener->local.isIPv6()?IP6T_SO_ORIGINAL_DST:SO_ORIGINAL_DST), destaddr, &socklen); + err = getsockopt(clientfd, IPPROTO_IPV6, IP6T_SO_ORIGINAL_DST, &destaddr, &socklen); + // + char str[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &destaddr, str, INET6_ADDRSTRLEN); + printf("%s\n", str); + + if (err) { ERROR("getdestaddr"); diff --git a/src/redir.h b/src/redir.h index ea0141c9..05e3b1a7 100644 --- a/src/redir.h +++ b/src/redir.h @@ -51,7 +51,7 @@ struct server ssize_t buf_len; ssize_t buf_idx; char *buf; // server send from, remote recv into - struct sockaddr_in destaddr; + struct sockaddr_in6 destaddr; struct enc_ctx *e_ctx; struct enc_ctx *d_ctx; struct server_ctx *recv_ctx; From d9eadc5c0959c2cf8d8c59607041132f48e7f9cc Mon Sep 17 00:00:00 2001 From: Blaok Date: Mon, 27 Oct 2014 02:45:28 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E6=AD=A3=E7=A1=AE=E8=8E=B7=E5=8F=96IPv6?= =?UTF-8?q?=E9=87=8D=E5=AE=9A=E5=90=91=E6=BA=90=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 已经证实IPv6重定向是可以正确获取源地址的,原有问题出在用于显示地址格式函数上面,字节序什么的似乎不对,只是显示有问题,直接打印结构体显示IPv6地址完全正确。 偷懒特么坑爹啊,早点自己打印地址就好了…… --- src/redir.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/redir.c b/src/redir.c index 67ad39b2..a73da115 100644 --- a/src/redir.c +++ b/src/redir.c @@ -627,16 +627,14 @@ static void accept_cb (EV_P_ ev_io *w, int revents) //err = getdestaddr(listener, &destaddr); printf("Connet server %s, port %s.\n",listener->remote_addr->host,listener->remote_addr->port); - printf("%d %s\n",listener->sock.sa_family,listener->sock.sa_data); socklen_t socklen = sizeof(destaddr); //err = getsockopt(listener->fd, (listener->local.isIPv6()?SOL_IP6:SOL_IP), (listener->local.isIPv6()?IP6T_SO_ORIGINAL_DST:SO_ORIGINAL_DST), destaddr, &socklen); - err = getsockopt(clientfd, IPPROTO_IPV6, IP6T_SO_ORIGINAL_DST, &destaddr, &socklen); - // - char str[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &destaddr, str, INET6_ADDRSTRLEN); - printf("%s\n", str); - - + err = getsockopt(clientfd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, &destaddr, &socklen); + unsigned char * ipv6addrr=(unsigned char*)(&destaddr.sin6_addr); + printf("sizeofaddr=%d connecting:",(int)(sizeof(destaddr.sin6_addr))); + for(int iii=0;iii<16;++iii) + printf("%02x",ipv6addrr[iii]); + printf("\n"); if (err) { ERROR("getdestaddr"); From 936eea67b4cbdef9aff8b2b40f0760714b39964e Mon Sep 17 00:00:00 2001 From: Blaok Date: Mon, 27 Oct 2014 06:04:07 +0800 Subject: [PATCH 3/5] =?UTF-8?q?IPv6=E9=87=8D=E5=AE=9A=E5=90=91=E8=BD=AC?= =?UTF-8?q?=E5=8F=91=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原来有一个设定地址类型的选项。所以接下来看看能不能整合一下IPv4和IPv6。 --- src/redir.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/redir.c b/src/redir.c index a73da115..7ed267b2 100644 --- a/src/redir.c +++ b/src/redir.c @@ -397,10 +397,9 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) // send destaddr char *ss_addr_to_send = malloc(BUF_SIZE); ssize_t addr_len = 0; - ss_addr_to_send[addr_len++] = 1; + ss_addr_to_send[addr_len++] = 4; - // handle IP V4 only - size_t in_addr_len = sizeof(struct in_addr); + size_t in_addr_len = sizeof(struct in6_addr); memcpy(ss_addr_to_send + addr_len, &server->destaddr.sin6_addr, in_addr_len); addr_len += in_addr_len; memcpy(ss_addr_to_send + addr_len, &server->destaddr.sin6_port, 2); @@ -628,7 +627,6 @@ static void accept_cb (EV_P_ ev_io *w, int revents) //err = getdestaddr(listener, &destaddr); printf("Connet server %s, port %s.\n",listener->remote_addr->host,listener->remote_addr->port); socklen_t socklen = sizeof(destaddr); - //err = getsockopt(listener->fd, (listener->local.isIPv6()?SOL_IP6:SOL_IP), (listener->local.isIPv6()?IP6T_SO_ORIGINAL_DST:SO_ORIGINAL_DST), destaddr, &socklen); err = getsockopt(clientfd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, &destaddr, &socklen); unsigned char * ipv6addrr=(unsigned char*)(&destaddr.sin6_addr); printf("sizeofaddr=%d connecting:",(int)(sizeof(destaddr.sin6_addr))); From 09061a642047b32c482c5664be3600fb07db5893 Mon Sep 17 00:00:00 2001 From: Blaok Date: Mon, 27 Oct 2014 07:20:51 +0800 Subject: [PATCH 4/5] =?UTF-8?q?redir=E6=A8=A1=E5=9D=97=E6=B7=BB=E5=8A=A0IP?= =?UTF-8?q?v6=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 没有找到直接探测IP版本的有效方法,暂时用试的。已经支持IPv4和IPv6透明代理转发。 --- src/redir.c | 50 +++++++++++++++++++++++++++++--------------------- src/redir.h | 2 +- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/redir.c b/src/redir.c index 7ed267b2..dab09f10 100644 --- a/src/redir.c +++ b/src/redir.c @@ -60,16 +60,20 @@ #define BUF_SIZE 2048 #endif -int getdestaddr( struct listen_ctx * listener, struct sockaddr_in *destaddr) +int getdestaddr(int fd, struct sockaddr_storage *destaddr) { -/* socklen_t socklen = sizeof(*destaddr); + socklen_t socklen = sizeof(*destaddr); int error=0; - // error = getsockopt(listener->fd, (listener->local.isIPv6()?SOL_IP6:SOL_IP), (listener->local.isIPv6()?IP6T_SO_ORIGINAL_DST:SO_ORIGINAL_DST), destaddr, &socklen); - if (error) + error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST,destaddr, &socklen); + if (error) // Didn't find a proper way to detect IP version. { - return -1; - }*/ + error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST,destaddr, &socklen); + if(error) + { + return -1; + } + } return 0; } @@ -397,12 +401,24 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) // send destaddr char *ss_addr_to_send = malloc(BUF_SIZE); ssize_t addr_len = 0; - ss_addr_to_send[addr_len++] = 4; + if(AF_INET6==server->destaddr.ss_family) // IPv6 + { + ss_addr_to_send[addr_len++] = 4; //Type 4 is IPv6 address - size_t in_addr_len = sizeof(struct in6_addr); - memcpy(ss_addr_to_send + addr_len, &server->destaddr.sin6_addr, in_addr_len); - addr_len += in_addr_len; - memcpy(ss_addr_to_send + addr_len, &server->destaddr.sin6_port, 2); + size_t in_addr_len = sizeof(struct in6_addr); + memcpy(ss_addr_to_send + addr_len, &(((struct sockaddr_in6*)&(server->destaddr))->sin6_addr), in_addr_len); + addr_len += in_addr_len; + memcpy(ss_addr_to_send + addr_len, &(((struct sockaddr_in6*)&(server->destaddr))->sin6_port), 2); + } + else //IPv4 + { + ss_addr_to_send[addr_len++] = 1; //Type 1 is IPv4 address + + size_t in_addr_len = sizeof(struct in_addr); + memcpy(ss_addr_to_send + addr_len, &((struct sockaddr_in*)&(server->destaddr))->sin_addr, in_addr_len); + addr_len += in_addr_len; + memcpy(ss_addr_to_send + addr_len, &((struct sockaddr_in*)&(server->destaddr))->sin_port, 2); + } addr_len += 2; ss_addr_to_send = ss_encrypt(BUF_SIZE, ss_addr_to_send, &addr_len, server->e_ctx); if (ss_addr_to_send == NULL) @@ -614,7 +630,7 @@ void close_and_free_server(EV_P_ struct server *server) static void accept_cb (EV_P_ ev_io *w, int revents) { struct listen_ctx *listener = (struct listen_ctx *)w; - struct sockaddr_in6 destaddr; + struct sockaddr_storage destaddr; int err; int clientfd = accept(listener->fd, NULL, NULL); @@ -624,15 +640,7 @@ static void accept_cb (EV_P_ ev_io *w, int revents) return; } - //err = getdestaddr(listener, &destaddr); - printf("Connet server %s, port %s.\n",listener->remote_addr->host,listener->remote_addr->port); - socklen_t socklen = sizeof(destaddr); - err = getsockopt(clientfd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, &destaddr, &socklen); - unsigned char * ipv6addrr=(unsigned char*)(&destaddr.sin6_addr); - printf("sizeofaddr=%d connecting:",(int)(sizeof(destaddr.sin6_addr))); - for(int iii=0;iii<16;++iii) - printf("%02x",ipv6addrr[iii]); - printf("\n"); + err = getdestaddr(clientfd, &destaddr); if (err) { ERROR("getdestaddr"); diff --git a/src/redir.h b/src/redir.h index 05e3b1a7..99e192c9 100644 --- a/src/redir.h +++ b/src/redir.h @@ -51,7 +51,7 @@ struct server ssize_t buf_len; ssize_t buf_idx; char *buf; // server send from, remote recv into - struct sockaddr_in6 destaddr; + struct sockaddr_storage destaddr; struct enc_ctx *e_ctx; struct enc_ctx *d_ctx; struct server_ctx *recv_ctx; From afe43922fa005d4d81f7386864476e32b8870eeb Mon Sep 17 00:00:00 2001 From: Blaok Date: Mon, 27 Oct 2014 08:26:06 +0800 Subject: [PATCH 5/5] =?UTF-8?q?redir=E5=A2=9E=E5=8A=A0IPv6=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/redir.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/redir.c b/src/redir.c index dab09f10..5f2c7c5e 100644 --- a/src/redir.c +++ b/src/redir.c @@ -110,7 +110,6 @@ int create_and_bind(const char *addr, const char *port) int opt = 1; setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); -// setsockopt(listen_sock, IPPROTO_IPV6, SO_REUSEADDR, &opt, sizeof(opt)); setsockopt(listen_sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));