Fwder
HenryHu(讨论 | 贡献)2011年9月16日 (五) 07:21的版本 (以内容“Category:程序 fwder的作用主要是通过一个HTTP proxy,转发HTTPS的连接。它主要是用在透明代理上的。 <source lang="c"> #include <sys/soc...”创建新页面)
页面上次由HenryHu编辑于13年前
fwder的作用主要是通过一个HTTP proxy,转发HTTPS的连接。它主要是用在透明代理上的。
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
char proxy_addr[] = "127.0.0.1";
char proxy_port[] = "8120";
int main()
{
sigignore(SIGCHLD);
struct addrinfo *ai;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
int ret = getaddrinfo("::", "8443", &hints, &ai);
if (ret)
{
fprintf(stderr, "failed to getaddrinfo: %s\n", gai_strerror(ret));
return 1;
}
int s = -1;
while (ai)
{
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (s < 0)
{
ai = ai->ai_next;
continue;
}
int val = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
ret = bind(s, ai->ai_addr, ai->ai_addrlen);
if (ret < 0)
{
close(s);
s = -1;
ai = ai->ai_next;
continue;
}
break;
}
if (s < 0)
{
perror("failed to create and bind sock: ");
return 1;
}
ret = listen(s, 10);
if (ret < 0)
{
perror("failed to listen: ");
return 1;
}
while (1)
{
struct sockaddr_storage cliaddr, myaddr;
socklen_t cl = sizeof(cliaddr);
socklen_t ml = sizeof(myaddr);
int client = accept(s, (struct sockaddr *)&cliaddr, &cl);
if (client < 0)
{
if (errno != ECONNABORTED)
break;
}
char host[256];
char serv[256];
getnameinfo((struct sockaddr *)&cliaddr, cl, host, sizeof(host),
serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV);
char myhost[256], myserv[256];
getsockname(client, (struct sockaddr *)&myaddr, &ml);
getnameinfo((struct sockaddr *)&myaddr, ml,
myhost, sizeof(myhost), myserv, sizeof(myserv),
NI_NUMERICHOST | NI_NUMERICSERV);
pid_t pid = fork();
if (pid == 0)
{
// close(stdout);
// close(stderr);
struct addrinfo newhint, *res;
memset(&newhint, 0, sizeof(newhint));
newhint.ai_family = AF_UNSPEC;
newhint.ai_socktype = SOCK_STREAM;
newhint.ai_flags = AI_NUMERICHOST;
ret = getaddrinfo(proxy_addr, proxy_port, &hints, &res);
if (ret)
{
// fprintf(stderr, "[%d] failed to getaddrinfo: %s\n", getpid(), gai_strerror(ret));
return 1;
}
if (strncmp(myhost, "::ffff:", 7) != 0)
{
return 1;
}
int xs = -1;
while (res)
{
xs = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (xs < 0)
{
res = res->ai_next;
continue;
}
int val = 1;
setsockopt(xs, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
break;
}
if (s < 0)
{
// perror("failed to create sock: ");
return 1;
}
ret = connect(xs, res->ai_addr, res->ai_addrlen);
if (ret < 0)
{
// perror("failed to connect: ");
return 1;
}
char *target = myhost + 7;
char req[1500];
char reply[1500];
char *ptr = reply;
if (strcmp(target, "78.16.49.15") == 0)
{
target = "199.59.148.87";
}
snprintf(req, sizeof(req), "CONNECT %s:%s HTTP/1.1\r\n\r\n", target, myserv);
int linelen = 0;
write(xs, req, strlen(req));
int status = 0;
while (1)
{
char c;
ret = read(xs, &c, 1);
if (ret <= 0)
break;
if (c == '\r')
{
read(xs, &c, 1);
if (c != '\n')
{
}
if (linelen == 0)
{
// reply end
break;
} else {
if (strncmp(reply, "HTTP/", 5) == 0)
{
// reply line
if (strstr(reply, " 200") != 0)
{
// OK
status = 1;
// printf("STATE OK\n");
} else {
status = 0;
// printf("STATE ERROR\n");
}
} else {
// other line
// printf("OTHER LINE\n");
}
}
linelen = 0;
// printf("NEW LINE\n");
} else {
reply[linelen] = c;
linelen++;
// printf("%c", c);
}
}
if (status > 0)
{
char buf[1500];
int max = xs;
if (client > xs) max = client;
max++;
int closed = 0;
while (1)
{
fd_set inout;
FD_ZERO(&inout);
FD_SET(xs, &inout);
FD_SET(client, &inout);
/*fprintf(stderr, "ok1 : %d\n", FD_ISSET(client, &inout));*/
/*fprintf(stderr, "ok2 : %d\n", FD_ISSET(xs, &inout));*/
/*printf("before select\n");*/
ret = select(max, &inout, NULL, NULL, NULL);
/*printf("after select\n");*/
if (ret == -1)
{
break;
}
if (FD_ISSET(xs, &inout))
{
/*printf("server data ready\n");*/
int len = read(xs, buf, sizeof(buf));
if (len <= 0)
{
closed++;
shutdown(client, SHUT_WR);
} else {
/*printf("got server data: %d\n", len);*/
ret = write(client, buf, len);
if (ret < len)
break;
}
}
if (FD_ISSET(client, &inout))
{
/*printf("client data ready\n");*/
int len = read(client, buf, sizeof(buf));
if (len <= 0)
{
closed++;
shutdown(xs, SHUT_WR);
} else {
/*printf("got data: %d bytes\n", len);*/
ret = write(xs, buf, len);
if (ret < len)
break;
}
}
if (closed >= 2)
break;
}
}
/*printf("EXIT\n");*/
shutdown(xs, SHUT_RDWR);
close(xs);
shutdown(client, SHUT_RDWR);
close(client);
return 0;
} else {
/* printf("new child %d serving %s:%s, at %s:%s\n", pid, host, serv,
myhost, myserv);*/
close(client);
}
}
return 0;
}