Files
2020-02-23 20:44:48 +08:00

373 lines
10 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<string>
#include <sys/time.h>
#include <sys/epoll.h>
#include <pthread.h>
#define SERV_TCP_PORT 9011 /* Local listening port number */
#define MAX_SIZE 4098
using namespace std;
int sockfd, newsockfd;
// simulate socks5-server
// usage:
// 1. "g++ -o server_t server_thread.cpp -lthread"
// 2. "./server_t"
void * thread_fun1(void * val){
int local_sockfd=newsockfd;
int remote_sockfd = *((int*)val);
char data[MAX_SIZE];
int datalen;
while(true){
datalen=recv(local_sockfd, data, sizeof(data), 0);
if (datalen<0) {
//nothing
}else if(datalen==0){
break;
}else{ // send to remote server
cout<<"get the data from localhost"<<endl;
if (send(remote_sockfd, data, datalen, 0) == -1) {
cout<<"cannot send to remote"<<endl;
}
}
}
return NULL;
}
void * thread_fun2(void * val){
int local_sockfd = newsockfd;
int remote_sockfd = *((int*)val);
char data[MAX_SIZE];
int datalen;
while(true){
datalen=recv(remote_sockfd, data, sizeof(data), 0);
if (datalen<0) {
//nothing
}else if(datalen==0){
break;
}else{
// send to localhost
cout<<"get the data from remote server"<<endl;
if (send(local_sockfd, data, datalen, 0) == -1) {
cout<<"cannot send to local"<<endl;
}
}
}
return NULL;
}
int main()
{
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 = 0;
//////////////////////////////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] != 5) {
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)
char msg2[2];
msg2[0] = (char)socks_vision;
msg2[1] = (char)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* 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)){
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);
}
// remote_addr.sin_port = htons((uint16_t)(long)r_port);
// htons() by hand
char cache_po=r_port[0];
r_port[0]=r_port[1];
r_port[1]=cache_po;
memcpy(&(remote_addr.sin_port),r_port,2);
connect(remote_sockfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr));
//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;
}
//Return connection information to client
char* connRrt;
if(addressType==1){
connRrt=new char[10];
connRrt[0]=socks_vision;
connRrt[1]=ui0;
connRrt[2]=ui0;
connRrt[3]=addressType;
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];
}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)
{
char 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* params[2];
// params[0]=(&newsockfd);
// params[1]=(&remote_sockfd);
// listen to the 9011
pthread_t tid1 ;
int ret1 = pthread_create(&tid1,NULL,thread_fun1,&remote_sockfd);
cout<<"ret1: "<<ret1<<endl;
// listen to the remote server
pthread_t tid2 ;
int ret2 = pthread_create(&tid2,NULL,thread_fun2,&remote_sockfd);
cout<<"ret2: "<<ret2<<endl;
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;
}