2020.9.11
网上看的都比较复杂,GITHUB找了一个多线程的相对简单的MicroSocks项目,花了几周时间(没办法,菜鸟一个)改了一下,改成单文件,测试OK。
/* wxl_socks5_proxy_server_v1.0
linux下最简单多线程单文件socks5代理proxy服务器程序(仅一个c文件,带详细注解)
wxleasyland@sina.com
2020.9
说明:
编译方法:gcc xxxx.c -pthread -o xxxx
一个线程对应一个客户端。
只支持TCP CONNECT方式和无用户验证。
*/
/* 感谢原作者。
程序主要在github开源项目MicroSocks基础上修改得到的:
https://github.com/rofl0r/microsocks
也少量参考了github开源项目HevSocks5Server:
https://github.com/heiher/hev-socks5-server
*/
/*
firefox可以选socks4还是socks5。
chrome 设置代理是在IE。 然后打开网页失败,抓包发现chrome是走SOCKS4版本。
在IE的“代理服务器设置”的“套接字”中,写成socks5://xxx.xxx.xxx.xxx就可以了,
chrome就会走SOCKS5版本了。 如果写成socks4://xxx.xxx.xxx.xxx,就又会走SOCKS4版本了。
firefox一下打开好几个网页窗口,大约线程数是接近200个,突发起来还是挺猛的。
chrome一下打开好几个网页窗口,大约线程数是50个,看来对socket的数量控制得比较好。
取单个线程堆栈为64K,占用内存不大,自己用用可以。
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stddef.h>
union sockaddr_union
{
struct sockaddr_in v4;
struct sockaddr_in6 v6;
};
// static pthread_mutex_t auth_ips_mutex = PTHREAD_MUTEX_INITIALIZER; //静态初始化互斥锁(暂未用到)
int g_totalthread=0; //总线程数量统计
int g_proxymode=0; //1表示正常CONNECT类型 4表示我自定义的DNS获取IP地址
int my_resolve(const char *host, unsigned short port, struct addrinfo** addr) //主要是getaddrinfo()得到远程主机的IP
{
struct addrinfo hints =
{
.ai_family = AF_UNSPEC, // AF_INET是IPV4 //AF_INET6是IPV6
.ai_socktype = SOCK_STREAM,
.ai_flags = AI_PASSIVE,
};
char port_buf[8];
snprintf(port_buf, sizeof port_buf, "%u", port);
return getaddrinfo(host, port_buf, &hints, addr);
//getaddrinfo函数用域名或主机名获取IP地址,返回的是一个sockaddr结构的链表。
//int getaddrinfo( const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result );
//返回值:0——成功,非0——出错
}
//ssize_t recv(int sockfd, void *buf, size_t len, int flags);
//return the number of bytes received, or -1 if an error occurred.
//When a stream socket peer has performed an orderly shutdown, the return value will be 0
ssize_t my_recv_all (int fd, void *buf, size_t len) //引用自HevSocks5Server项目
{
ssize_t s;
size_t size = 0;
if(len<=0) return len;
retry:
s = recv (fd, buf + size, len - size, MSG_WAITALL);
if (s < 0) //阻塞下出错
{
return s;
}
if (s == 0) //对方中止连接
return -1;
size += s;
if (size < len)
goto retry;
return size;
}
void send_error1(int fd, unsigned char d) //返回错误信息给客户
{
unsig