Files
http_vpn/http_vpn_20191209/server/Socks5Server.cpp
T
2020-02-23 20:44:48 +08:00

373 lines
9.9 KiB
C++

// simulate socks5-server. coding by wefree in 2019.12
#include "Socks5Server.h"
using namespace std;
// listen to the local port
void Socks5Server::ndn_listen_local(string prefix){
mndn_socket.listen(prefix.data()) ;
cout << "listen on : " << prefix << endl ;
}
// waiting for the local port's connection
string Socks5Server::ndn_accept_local(string new_prefix) {
char buff[1000] ;
memset(buff,0,1000) ;
cout<<"Waitting connection [socks5-server] ..."<<endl;
int read_n = mndn_socket.read(buff,1000) ;
cout<<"Acceptted a connection [socks5-server]"<<endl;
string client_prefix = buff ;
cout << "client_prefix : " << client_prefix << endl ;
return client_prefix ;
}
// a handshake for the sub-negotiation method
int Socks5Server::ndn_negotShake(Ndn_socket &ndn_socket){
int flag=0;
//Get 2 bytes of information from the client
// - socks version number, total number of negotiation methods
char buf1[1];
char buf2[2];
cout << "ndn_negotShake before read" << endl ;
// 测试代码段BEGIN
// char buf8[8];
// char buf10[10];
// char buf20[20];
// if (ndn_socket.read(buf20 , 20) < 0) {
// cout<<"cannot test the metaphysics bug"<<endl;
// flag=1;
// return flag;
// }else{
// for(int i=0;i<20;i++){ // to test it.
// printf("%x--%c ", buf20[i],buf20[i]);
// }
// flag=1;
// return flag;
// }
// 测试代码段END
if (ndn_socket.read(buf2 , 2) < 0) {
cout<<"cannot get version-nmethod"<<endl;
flag=1;
return flag;
}
if ((uint8_t)buf2[0] != this->socks_vision) {
cout<<"socks version is wrong"<<endl;
cout<<"version-nmethod: ";
printf("%x--%c ", buf2[0],buf2[0]);
printf("%x--%c \n", buf2[1],buf2[1]);
flag=1;
return flag;
}
if ((uint8_t)buf2[1] <= 0) {
cout<<"nmethod is wrong"<<endl;
cout<<"version-nmethod: ";
printf("%x--%c ", buf2[0],buf2[0]);
printf("%x--%c \n", buf2[1],buf2[1]);
flag=1;
return flag;
}
cout<<"version-nmethod: ";
printf("%x ", buf2[0]);
printf("%x \n", buf2[1]);
//negotiation methods
int nmethods = (uint8_t)buf2[1];
// the method contains 0 when the m_flag==1
int m_flag = 0;
for (int i = 0; i < nmethods; i++) {
ndn_socket.read(buf1,1) ;
if ((uint8_t)(buf1[0]) == 0) {
m_flag = 1;
}
cout<<"nmethods: ";
printf("%x\n", buf1[0]);
}
if (m_flag == 0) {
cout<<"methods donot have 0"<<endl;
flag=1;
return flag;
}
//Return request reply (no sub-negotiation required)
uint8_t msg2[2];
msg2[0] = this->socks_vision;
msg2[1] = this->ui0;
if (ndn_socket.write(msg2,2) < 0) {
cout<<"cannot send socks-methond-reply"<<endl;
flag=1;
return flag;
}
return flag;
}
// a handshake for the connection information
// to remote server
pair<int,int> Socks5Server::ndn_connShake(Ndn_socket &ndn_socket){
// right flag, the loop is going on when th flag==0
int flag=0;
char buf4[4];
if (ndn_socket.read(buf4,4) < 0 ) {
cout<<"cannot get version-cmd-_-addressType"<<endl;
flag=1;
return make_pair(-1,flag);
}
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]);
flag=1;
return make_pair(-1,flag);
}
uint8_t cmd = (uint8_t)buf4[1];
if(cmd!=1){
cout<<"cmd is not 1"<<endl;
flag=1;
return make_pair(-1,flag);
}
uint8_t addressType = (uint8_t)buf4[3];
if(addressType!=1){
cout<<"address is not ipv4"<<endl;
flag=1;
return make_pair(-1,flag);
}
//Get the IP address of the destination server of URL request from the client
char* r_address;
char* domin_address;
int remote_addr_length=4;
if (addressType == 1) {//ipv4
remote_addr_length=4;
r_address=new char[4];
if (ndn_socket.read(r_address,4) < 0) {
cout<<"cannot get the ipv4\n"<<endl;
flag=1;
return make_pair(-1,flag);
}
printf("ipv4: %d %d",(uint8_t)r_address[0],(uint8_t)r_address[1]);
printf(" %d %d\n",(uint8_t)r_address[2],(uint8_t)r_address[3]);
}else{
cout<<"address is not ipv4"<<endl;
flag=1;
return make_pair(-1,flag);
}
//Listener port of destination server for URL request from client
char r_port[2];
//if (recv(newsockfd, r_port, 2, 0) == -1) {
if (ndn_socket.read(r_port,2) < 0) {
cout<<"cannot get the port\n"<<endl;
flag=1;
return make_pair(-1,flag);
}
printf("port: %d %d\n", (uint8_t)r_port[0],(uint8_t)r_port[1]);
//When the connection to the remote server is successful,
// remote server
int remote_sockfd;
try
{
if (cmd == 1) {
if (addressType == 1){//ipv4
//Connect to remote destination server
struct sockaddr_in remote_addr;
remote_sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero((char *)&remote_addr, sizeof(remote_addr));
remote_addr.sin_family = AF_INET;
memcpy(&(remote_addr.sin_addr.s_addr),r_address,remote_addr_length);
memcpy(&(remote_addr.sin_port),r_port,2);
cout<<"connecting to ipv4..."<<endl;
int res_c=connect(remote_sockfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr));
if(res_c==-1){
cout<<"connect error"<<endl;
flag=1;
return make_pair(remote_sockfd,flag);
}else{
cout<<"connected ipv4"<<endl;
printf("Connected to %s:%d\n",inet_ntoa(remote_addr.sin_addr),remote_addr.sin_port);
}
}else{
//...
}
}
else {
printf("cmd is not connection\n");
flag=1;
return make_pair(remote_sockfd,flag);
}
//Return connection information to client
uint8_t *connRrt;
if(addressType==1){//ipv4
//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:"<<inet_ntoa(cs_addr.sin_addr)<<":"<<ntohs(cs_addr.sin_port)<<endl;
// return info
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),remote_addr_length);
memcpy(&connRrt[8],&(cs_addr.sin_port),2);
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;
if (ndn_socket.write(connRrt,10) < 0) {
printf("cannot send url-reply\n");
flag=1;
return make_pair(remote_sockfd,flag);
}
}else{}
}
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 (ndn_socket.write(err,6) < 0) {
printf("cannot send url-err-reply\n");
flag=1;
return make_pair(remote_sockfd,flag);
}
}
return make_pair(remote_sockfd,flag);
};
// data transmission shake
void Socks5Server::ndn_transData(string new_prefix , string client_prefix){
pid_t fpid1;
while ( ( fpid1 = fork() ) < 0 ){
cout << "create child process failled. Retry..." << endl;
}
if ( 0 == fpid1 ) {
cout<<"child process beginning: "<<endl;
Ndn_socket ndn_socket ;
ndn_socket.listen(new_prefix.data()) ;
ndn_socket.set_daddr(client_prefix.data()) ;
cout << "new server ndnsocket's daddr :" << ndn_socket.get_daddr() << endl ;
// 将服务器端与客户端进程对接的ndn_socket的兴趣前缀发送给client
cout<<"new_prefix: "<<new_prefix<<endl;
ndn_socket.write(new_prefix) ;
if(this->ndn_negotShake(ndn_socket)>0){
cout<<"negotShake error"<<endl;
ndn_socket.close() ;
exit(0) ;
}
pair<int,int> pairval= ndn_connShake(ndn_socket) ;
if(pairval.second>0){
cout<<"connShake error"<<endl;
if(pairval.first>0){
close(pairval.first);
}
ndn_socket.close() ;
exit(0);
}
int remote_sockfd = pairval.first;
printf("Data transmission is beginning.\n");
void *sockfds[2] = {&ndn_socket,&remote_sockfd} ;
pthread_t ptid1, ptid2 ;
pthread_create(&ptid1 , NULL , ndn_thread1 , sockfds) ;
pthread_create(&ptid2 , NULL , ndn_thread2 , sockfds) ;
pthread_join(ptid1,NULL) ;
pthread_join(ptid2,NULL) ;
cout<<"child process exit()"<<endl;
// close the fd in the son process
close(this->sockfd);
// exit the son process
exit(0);
}
};
// forever listenner function
void Socks5Server::ndn_forever(){
while(true){
string new_prefix = this->listen_prefix+ to_string(p_port_seq++) ;
string client_prefix = this->ndn_accept_local(new_prefix) ;
ndn_transData(new_prefix, client_prefix ) ;
}
};
// server start
void Socks5Server::start(){
this->ndn_listen_local(base_listen_prefix) ;
this->ndn_forever() ;
mndn_socket.close() ;
};
// transfer data from local server host to remote-server
void *Socks5Server::ndn_thread1(void *val){
Ndn_socket *ndn_socketp = *((Ndn_socket**)val) ;
int remote_sockfd = **((int**)val + 1) ;
char *data=new char[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen = ndn_socketp->read(data , MAX_SIZE) ;
cout << "**************recv from ndn_socket datalen = " << datalen << endl ;
if (datalen<= 0) {
break ;
}else{ // send to remote server
send_len = send(remote_sockfd, data, datalen, 0) ;
cout << "****************send to remote_sockfd len = " << send_len << endl ;
}
}
cout << ">>>>>>>>>>>>>>>>>>>>thread1 end" << endl ;
delete data;
ndn_socketp->close() ;
close(remote_sockfd) ;
return NULL;
}
// transfer data form remote-server to local server host
void *Socks5Server::ndn_thread2(void *val){
Ndn_socket *ndn_socketp = *((Ndn_socket**)val) ;
int remote_sockfd = **((int**)val + 1) ;
char *data=new char[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(remote_sockfd, data, MAX_SIZE, 0);
cout << "************recv from remote_sock datalen = " << datalen << endl ;
if (datalen <= 0) {
break;
}else{
send_len = ndn_socketp->write(data, datalen) ;
cout << "**************send to ndn_socket len = " << send_len << endl ;
}
}
cout << ">>>>>>>>>>>>>>>>>>>>thread2 end" << endl ;
delete data;
ndn_socketp->close() ;
close(remote_sockfd) ;
return NULL;
}