mirror of
https://gitee.com/willfree/http_vpn.git
synced 2026-06-08 17:09:39 +08:00
385 lines
11 KiB
C++
385 lines
11 KiB
C++
#include <iostream>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <netdb.h>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <unistd.h>
|
|
#include <cstring>
|
|
#include <sys/time.h>
|
|
#define SERV_TCP_PORT 9011 /* Local listening port number */
|
|
#define MAX_SIZE 4098
|
|
|
|
using namespace std;
|
|
|
|
// simulate socks5-server
|
|
// usage:
|
|
// 1. "g++ -o server server.cpp"
|
|
// 2. "./server"
|
|
// 3. "curl -v --socks5 127.0.0.1:9011 https://github.com" => ssl version error(https)
|
|
// 4. "curl -v --socks5 127.0.0.1:9011 http://github.com>>g.html" => no error(http ipv4)
|
|
// 5. "curl -v --socks5 127.0.0.1:9011 http://www.gnu.org/software/gettext/manual/gettext.html>>ge.html"
|
|
// => no error (http ipv6)
|
|
|
|
int main()
|
|
{
|
|
|
|
int sockfd, newsockfd;
|
|
socklen_t clilen;
|
|
struct sockaddr_in cli_addr, serv_addr;
|
|
int port;
|
|
char string[MAX_SIZE];
|
|
int len;
|
|
|
|
port = SERV_TCP_PORT;
|
|
|
|
uint8_t socks_vision = 5;
|
|
int remote_sockfd;
|
|
struct sockaddr_in remote_addr;
|
|
int remote_addr_length=6;//the length of remote server address
|
|
uint8_t ui0 = 0;
|
|
uint8_t ui5 = 5;
|
|
|
|
//////////////////////////////Listen to local port number 9011-Begin//////////////////////
|
|
/* open a TCP socket (an Internet stream socket) */
|
|
(sockfd = socket(AF_INET, SOCK_STREAM, 0));
|
|
|
|
/* bind the local address, so that the cliend can send to server */
|
|
bzero((char *)&serv_addr, sizeof(serv_addr));
|
|
serv_addr.sin_family = AF_INET;
|
|
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
serv_addr.sin_port = htons(port);
|
|
|
|
bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
|
|
|
|
listen(sockfd, 10);
|
|
|
|
//////////////////////////////Listen to local port number 9011-End//////////////////////
|
|
|
|
while (true) {
|
|
//////////////////////////////1.Socks5 connection request negotiation-Begin//////////////////////
|
|
//Waiting for connection prompts
|
|
cout<<"Accepting connection from: localhost"<<endl;
|
|
//+ serv_addr.sin_addr.s_addr+" "+ serv_addr.sin_port);
|
|
//Waiting for Client Connection
|
|
clilen = sizeof(cli_addr);
|
|
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
|
|
if (newsockfd < 0) {
|
|
cout<<"can't bind local address"<<endl;
|
|
}
|
|
|
|
//Get 2 bytes of information from the client
|
|
// - socks version number, total number of negotiation methods
|
|
char buf1[1];
|
|
char buf2[2];
|
|
char buf4[4];
|
|
if (recv(newsockfd, buf2, 2, 0) == -1) {
|
|
cout<<"cannot get version-nmethod"<<endl;
|
|
}
|
|
|
|
if ((uint8_t)buf2[0] != socks_vision) {
|
|
cout<<"version is wrong"<<endl;
|
|
close(newsockfd);
|
|
continue;
|
|
}
|
|
|
|
if ((uint8_t)buf2[1] <= 0) {
|
|
cout<<"nmethod is wrong"<<endl;
|
|
close(newsockfd);
|
|
continue;
|
|
}
|
|
cout<<"version-nmethod: ";
|
|
printf("%x ", buf2[0]);
|
|
printf("%x \n", buf2[1]);
|
|
//negotiation methods
|
|
int nmethods = (uint8_t)buf2[1];
|
|
int flag = 0;
|
|
|
|
for (int i = 0; i < nmethods; i++) {
|
|
recv(newsockfd, buf1, 1, 0);
|
|
if ((uint8_t)(buf1[0]) == 0) {
|
|
flag = 1;
|
|
}
|
|
cout<<"nmethods: ";
|
|
printf("%x\n", buf1[0]);
|
|
}
|
|
|
|
if (flag == 0) {
|
|
cout<<"methods donot have 0"<<endl;
|
|
close(newsockfd);
|
|
continue;
|
|
}
|
|
|
|
//Return request reply (no sub-negotiation required)
|
|
uint8_t msg2[2];
|
|
msg2[0] = socks_vision;
|
|
msg2[1] = ui0;
|
|
|
|
if (send(newsockfd, msg2, 2, 0) == -1) {
|
|
cout<<"cannot send socks-methond-reply"<<endl;
|
|
}
|
|
//////////////////////////////1.Socks5 connection request negotiation-End//////////////////////
|
|
|
|
//////////////////////////////2.Packet parsing of URL requests - Begin//////////////////////
|
|
//Get the first four bytes of information such as the address type of URL request
|
|
// from the client
|
|
if (recv(newsockfd, buf4, 4, 0) == -1) {
|
|
cout<<"cannot get version-cmd-_-addressType"<<endl;
|
|
}
|
|
cout<<"version-cmd-_-addressType: ";
|
|
printf("%x ", buf4[0]);
|
|
printf("%x ", buf4[1]);
|
|
printf("%x \n", buf4[3]);
|
|
if ((uint8_t)buf4[0] != 5) {
|
|
cout<<"version is wrong. version-cmd-_-addressType: ";
|
|
printf("%x ", buf4[0]);
|
|
printf("%x ", buf4[1]);
|
|
printf("%x \n", buf4[3]);
|
|
close(newsockfd);
|
|
continue;
|
|
}
|
|
uint8_t cmd = (uint8_t)buf4[1];
|
|
uint8_t addressType = (uint8_t)buf4[3];
|
|
//Get the IP address of the destination server of URL request from the client
|
|
char* r_address;
|
|
char* domin_address;
|
|
|
|
if (addressType == 1) {//ipv4
|
|
remote_addr_length=4;
|
|
r_address=new char[4];
|
|
if (recv(newsockfd, r_address, 4, 0) == -1) {
|
|
cout<<"cannot get the ipv4\n"<<endl;
|
|
}
|
|
printf("ipv4: %d %d %d %d\n",(uint8_t)r_address[0],(uint8_t)r_address[1],(uint8_t)r_address[2],(uint8_t)r_address[3]);
|
|
}
|
|
// else if (addressType == 3) {// domain name
|
|
// char addr_len[1];
|
|
// recv(newsockfd, addr_len, 1, 0);
|
|
// r_address=new char[(long)addr_len];
|
|
// remote_addr_length=(long)addr_len;
|
|
// if (recv(newsockfd, r_address, (long)addr_len, 0) == -1) {
|
|
// cout<<"cannot get the domin ip"<<endl;
|
|
// }
|
|
// // for(int i=0;i<(long)addr_len;i++){
|
|
// // printf("%x ",r_address[i]);
|
|
// // }
|
|
// struct hostent *h;
|
|
// if ((h = gethostbyname(r_address)) == NULL) { /* Get address information */
|
|
// cout<<"domin is wrong"<<endl;
|
|
// close(newsockfd);
|
|
// continue;
|
|
// }
|
|
// domin_address= inet_ntoa(*((struct in_addr *)h->h_addr));
|
|
// printf("domin: %s\n",domin_address);
|
|
// }else if(addressType==4){//ipv6
|
|
// remote_addr_length=16;
|
|
// r_address=new char[16];
|
|
// if (recv(newsockfd, r_address, 16, 0) == -1) {
|
|
// cout<<"cannot get the ipv6\n"<<endl;
|
|
// }
|
|
// printf("ipv6: (...)\n");
|
|
// }
|
|
|
|
//Listener port of destination server for URL request from client
|
|
char r_port[2];
|
|
if (recv(newsockfd, r_port, 2, 0) == -1) {
|
|
cout<<"cannot get the port\n"<<endl;
|
|
close(newsockfd);
|
|
continue;
|
|
}
|
|
printf("port: %d %d\n", (uint8_t)r_port[0],(uint8_t)r_port[1]);
|
|
//////////////////////////////2.Packet parsing of URL requests-End//////////////////////
|
|
|
|
//////////////////////////////3.Connect to remote destination server-Begin//////////////////////
|
|
//When the connection to the remote server is successful,
|
|
//the rep_flag tag is 0
|
|
int rep_flag = 5;
|
|
try
|
|
{
|
|
if (cmd == 1) {
|
|
//Connect to remote destination server
|
|
remote_sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
bzero((char *)&remote_addr, sizeof(remote_addr));
|
|
remote_addr.sin_family = AF_INET;
|
|
if ((addressType == 1)||(addressType==4)){
|
|
// remote_addr.sin_addr.s_addr = inet_addr(r_address);
|
|
memcpy(&(remote_addr.sin_addr.s_addr),r_address,remote_addr_length);
|
|
}else if(addressType == 3){
|
|
// remote_addr.sin_addr.s_addr = inet_addr(domin_address);
|
|
memcpy(&(remote_addr.sin_addr.s_addr),domin_address,remote_addr_length);
|
|
}
|
|
|
|
// remote_addr.sin_port = htons((uint16_t)(long)r_port);
|
|
memcpy(&(remote_addr.sin_port),r_port,2);
|
|
cout<<"connecting..."<<endl;
|
|
int res_c=connect(remote_sockfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr));
|
|
if(res_c==-1){
|
|
cout<<"connect error"<<endl;
|
|
close(newsockfd);
|
|
close(remote_sockfd);
|
|
continue;
|
|
}
|
|
cout<<"connected"<<endl;
|
|
|
|
//Print Successful Connection Tips
|
|
if (addressType == 1){
|
|
printf("Connected to %s:%d\n",inet_ntoa(remote_addr.sin_addr),remote_addr.sin_port);
|
|
// printf("Connected to %d. %d. %d. %d: %d %d\n",(uint8_t)r_address[0],(uint8_t)r_address[1],(uint8_t)r_address[2],(uint8_t)r_address[3],(uint8_t)r_port[0],(uint8_t)r_port[1]);
|
|
}else if(addressType == 3){
|
|
printf("Connected to %s: %d %d\n",domin_address,(uint8_t)r_port[0],(uint8_t)r_port[1]);
|
|
}else if(addressType==4){
|
|
printf("Connected to ipv6(...): %d %d\n",(uint8_t)r_port[0],(uint8_t)r_port[1]);
|
|
}
|
|
|
|
}
|
|
else {
|
|
printf("cmd is not connection");
|
|
close(newsockfd);
|
|
continue;
|
|
}
|
|
|
|
//getsocketname()
|
|
sockaddr_in cs_addr;
|
|
memset(&cs_addr,0,sizeof(cs_addr));
|
|
int cs_len=sizeof(cs_addr);
|
|
int res_sn=getsockname(remote_sockfd,(struct sockaddr *)&cs_addr,(socklen_t *)&cs_len);
|
|
|
|
cout<<"Current connection Socket IP:"<<inet_ntoa(cs_addr.sin_addr)<<":"<<ntohs(cs_addr.sin_port)<<endl;
|
|
|
|
//Return connection information to client
|
|
uint8_t *connRrt;
|
|
if(addressType==1){
|
|
connRrt=new uint8_t[10];
|
|
connRrt[0]=socks_vision;
|
|
connRrt[1]=ui0;
|
|
connRrt[2]=ui0;
|
|
connRrt[3]=addressType;
|
|
memcpy(&connRrt[4],&(cs_addr.sin_addr.s_addr),4);
|
|
memcpy(&connRrt[8],&(cs_addr.sin_port),2);
|
|
// for(int i=0;i<4;i++){
|
|
// connRrt[4+i]=(uint8_t)r_address[i];
|
|
// }
|
|
// connRrt[8]=(uint8_t)r_port[0];
|
|
// connRrt[9]=(uint8_t)r_port[1];
|
|
cout<<"the reply ip:"<<endl;
|
|
for(int i=0;i<4;i++){
|
|
printf("%d ",(uint8_t)connRrt[4+i]);
|
|
}
|
|
cout<<endl;
|
|
cout<<"the reply port:"<<endl;
|
|
for(int i=0;i<2;i++){
|
|
printf("%d ",(uint8_t)connRrt[8+i]);
|
|
}
|
|
cout<<endl;
|
|
}
|
|
// }else if(addressType==3){
|
|
// connRrt=new char[6+remote_addr_length];
|
|
// connRrt[0]=socks_vision;
|
|
// connRrt[1]=ui0;
|
|
// connRrt[2]=ui0;
|
|
// connRrt[3]=addressType;
|
|
// for(int i=0;i<remote_addr_length;i++){
|
|
// connRrt[4+i]=(uint8_t)r_address[i];
|
|
// }
|
|
// connRrt[4+remote_addr_length]=(uint8_t)r_port[0];
|
|
// connRrt[5+remote_addr_length]=(uint8_t)r_port[1];
|
|
// }else if(addressType==4){
|
|
// connRrt=new char[22];
|
|
// connRrt[0]=socks_vision;
|
|
// connRrt[1]=ui0;
|
|
// connRrt[2]=ui0;
|
|
// connRrt[3]=addressType;
|
|
// for(int i=0;i<16;i++){
|
|
// connRrt[4+i]=(uint8_t)r_address[i];
|
|
// }
|
|
// connRrt[20]=(uint8_t)r_port[0];
|
|
// connRrt[21]=(uint8_t)r_port[1];
|
|
// }
|
|
|
|
if (send(newsockfd, connRrt, sizeof(connRrt), 0) == -1) {
|
|
printf("cannot send url-reply\n");
|
|
}
|
|
rep_flag = 0;
|
|
}
|
|
catch (exception& e)
|
|
{
|
|
uint8_t err[6];
|
|
err[0] = socks_vision;
|
|
err[1] = ui5;
|
|
err[2] = ui0;
|
|
err[3] = addressType;
|
|
err[4] = ui0;
|
|
err[5] = ui0;
|
|
if (send(newsockfd, err, 6, 0) == -1) {
|
|
printf("cannot send url-err-reply\n");
|
|
}
|
|
}
|
|
//////////////////////////////3.Connect to remote destination server-End//////////////////////
|
|
|
|
//////////////////////////////4.Data Exchange (Web Request)-Begin//////////////////////
|
|
if ((cmd == 1) && (rep_flag == 0)) {
|
|
printf("Data transmission is beginning.\n");
|
|
int count=0;
|
|
fd_set readfds;
|
|
while (true) {
|
|
count++;
|
|
|
|
printf("data transmission: %d\n",count);
|
|
|
|
// if(count==50){
|
|
// break;
|
|
// }
|
|
// cout<<"test1"<<endl;
|
|
FD_ZERO(&readfds);
|
|
// cout<<"test2"<<endl;
|
|
FD_SET(newsockfd, &readfds);
|
|
// cout<<"test3"<<endl;
|
|
FD_SET(remote_sockfd, &readfds);
|
|
cout<<"selecting..."<<endl;
|
|
select(remote_sockfd+1, &readfds, NULL, NULL, NULL);
|
|
cout<<"selected"<<endl;
|
|
char data[MAX_SIZE];
|
|
//listen from client
|
|
if (FD_ISSET(newsockfd, &readfds)) {
|
|
int datalen=recv(newsockfd, data, MAX_SIZE, 0);
|
|
if(datalen<=0){
|
|
cout<<"local is unconnected."<<endl;
|
|
break;
|
|
}else{
|
|
if (send(remote_sockfd, data, datalen, 0) <= 0) {
|
|
printf("cannot send data to dist-server\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//listen from remote server
|
|
if (FD_ISSET(remote_sockfd, &readfds)) {
|
|
int datalen=recv(remote_sockfd, data, MAX_SIZE, 0);
|
|
if(datalen<=0){
|
|
cout<<"remote server is unconnected."<<endl;
|
|
break;
|
|
}else{
|
|
if (send(newsockfd, data, datalen, 0) <= 0) {
|
|
printf("cannot send data to localhost\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
printf("Data transmission is finished.\n");
|
|
close(remote_sockfd);
|
|
printf("The remote_sockfd is closed.\n");
|
|
}
|
|
close(newsockfd);
|
|
printf("The newsockfd is closed.\n");
|
|
//////////////////////////////4.Data Exchange (Web Request)-End//////////////////////
|
|
}
|
|
close(sockfd);
|
|
printf("The sockfd is closed.\n");
|
|
return 0;
|
|
}
|
|
|