socks5_demo及http_vpn项目

This commit is contained in:
my-style
2020-02-23 20:44:48 +08:00
commit 774e4254f1
108 changed files with 8069 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
# http-vpn ("http-ndn-http")
运行环境:
1、安装NFD
2、配置:
$ sudo vim /usr/local/etc/ndn/nfd.conf
查找到以下行:
cs_unsolicited_policy XXX (XXX表示任意值)
改为:
cs_unsolicited_policy admit-local
3、重启NFD
$ nfd-stop
$ nfd-start
运行方法:
1、打开client
1)进入client文件夹
2$ make
3$ ./client -s /aaa/nfd/vpn/server -c /aaa/nfd/vpn/client
2、打开server
1)进入server文件夹
2$ make
3$ ./server -s /aaa/nfd/vpn/server
测试方法:
1、命令行:
curl -v --socks5 127.0.0.1:8888 https://www.baidu.com
curl -v --socks5 127.0.0.1:8888 https://dlie.sogoucdn.com/se/sogou_explorer_8.6_0903.exe -o test.exe
http://mirrors.huaweicloud.com/ubuntukylin/ubuntukylin-19.04-enhanced-amd64.iso
2、浏览器:
设置浏览器socks代理端口为8888
已经修复的bug或做出的改进:
1、ctrl+c终止程序之后bind不通的问题;
2、修改了接收函数里面的数据存储数组的定义方式【new方式分配】;
3、将原来的r_queue升级为QueuePool,使得数据段顺序接收;
4、2019.12.04 将buff_size调整到8000,无内存溢出;
5、2019.12.05 ndn_socket可以接收不同地址的数据(重置QueuePool的wantSeq),
也可以向不同地址发送数据(重置本身的seq属性);
6、2019.12.05 在使用curl命令请求百度页面时概率随机性请求到;
测试情况:握手阶段请求到的协议信息是数据传输前建立ccn_p2p连接发送的消息'/aaa/nfd/vpn/client0'
推测原因:
1.1 兴趣包前缀混乱:
client端的ndn_socket的预兴趣包声明周期较长,这个预兴趣包有一定概率发送到server端
新建的ndn_socket建立的兴趣监听中。
1.2 或ccn_p2p的read()函数出现BUG
或r_queue中读取数据之后进行rev_n操作这两个操作不是原子性质的操作,
导致server方接收数据之后立即进行再次读取数据,会将原来已经读过的数据再次读取,
不过这种猜测的问题在于,server方进行协议握手的ndn_socket并非是原来接收prefix的ndn_socket。。。
1.3 改造问题
由于我们在发送数据段的时候编号进行了回卷,即同一个ndn_socket发送的前后两个数据,如果是发送给两个ndn_socket目的地址的话,这两个数据的预兴趣包及数据包的名称是一致的。这出现了冲突。
解决方法:
first try
如果是1.1的错误,那末错误出现的最大可能是因为“最长前缀匹配原则”,由于'/aaa/nfd/vpn/server0'和
'/aaa/nfd/vpn/server'对'/aaa/nfd/vpn/client0'发出的预兴趣包'/aaa/nfd/vpn/server'的匹配长度一致,因此两个ndn_socket都可能接收到缓存中的兴趣包。
这里作如下改进以避免以上问题,设置主监听ndn_socket的兴趣前缀为'/aaa/nfd/vpn/client_base'和'/aaa/nfd/vpn/server_base',以使得前缀匹配更加精准。
failed。
second try
直接写死主监听的兴趣前缀:/server_base /client_base
【当然这么搞在参数意义上看不大通顺,先这么测试一把】
failed。成功验证了不是前缀的问题。
将代码回卷到first try,来保证参数意义的合理性。
thrid try
根据1.3的改造问题所述。
我们可以在修改特定ndn_socket目的地址之后,不仅将该特定ndn_socket的seq重置为0,并将其start_ts进行重置,以保证后续的数据的预兴趣包Block字段及数据段的命名,均不与之前产生的数据发生冲突。
success.
尚未解决bug
1、ndn_p2p中的丢包问题的解决(需要进行丢包测试方法的设计);
@@ -0,0 +1,177 @@
#include<iostream>
#include "PriorQueue.h"
using namespace std;
PriorQueue::PriorQueue(){
//设置默认参数
this->headSeq=0;
this->count=0;
this->dataTail=0;
this->maxNum=1;
// 根据maxNum初始化dataPriorQueue
this->dataPriorQueue.resize(this->maxNum);
// 初始化条件锁、互斥锁
// pthread_cond_init(&full_cond, NULL) ;
// pthread_mutex_init(&mutex , NULL) ;
}
PriorQueue::~PriorQueue(){
}
// 设置头序列号
void PriorQueue::setHeadSeq(unsigned int seqFirst){
this->headSeq=seqFirst;
}
// 获取头序列号
unsigned int PriorQueue::getHeadSeq(){
return this->headSeq;
}
// 设置所属数据包总长度
void PriorQueue::setDataLen(unsigned int datalen){
this->datalen=datalen;
}
// 获取所属数据包总长度
unsigned int PriorQueue::getDataLen(){
return this->datalen;
}
// 设置队列最大容量
void PriorQueue::setMaxNum(int seq_n){
this->maxNum=seq_n;
// 根据maxNum初始化dataPriorQueue
this->dataPriorQueue.resize(this->maxNum);
}
// 获取队列最大容量
int PriorQueue::getMaxNum(){
return this->maxNum;
}
// 设置最后一个数据段的长度
void PriorQueue::setDataTail(int dataTail){
this->dataTail=dataTail;
}
// 获取最后一个数据段的长度
int PriorQueue::getDataTail(){
return this->dataTail;
}
// 解析数据段
int PriorQueue::parseData(const char* dataSeg,int len,char* rawdata){
unsigned int seq;
unsigned int seq_first;
unsigned int datap_len;
// cout<<"szof(dataSeg): "<<sizeof(dataSeg)<<endl;
// cout<<"strlen(dataSeg): "<<strlen(dataSeg)<<endl;
// cout<<"**********the parse result is: ***********"<<endl;
// rawdata=(char*)malloc((len-HEAD_LEN)*sizeof(char));
memcpy(&seq,&dataSeg[0],4);
// cout<<"seq: "<<seq<<endl;
memcpy(&seq_first,&dataSeg[4],4);
// cout<<"seq_first: "<<seq_first<<endl;
memcpy(&datap_len,&dataSeg[8],4);
// cout<<"datap_len: "<<datap_len<<endl;
if(this->count==0){
this->setHeadSeq(seq_first); //所属数据包首序列号
this->setDataLen(datap_len); //所属数据包的数据总长度
int queue_capacity;
queue_capacity=datap_len/DATASEG_SZ;
if(datap_len%DATASEG_SZ!=0){
queue_capacity++;
this->setDataTail(datap_len%DATASEG_SZ);
}
this->setMaxNum(queue_capacity);
}
memcpy(rawdata,&dataSeg[12],(len-HEAD_LEN));
// cout<<"rawdata: "<<rawdata<<endl;
// cout<<"******************************************"<<endl;
return seq;
}
// 缓存数据段:数据段、数据段长度
void PriorQueue::setDataSegment(const char* datas,int len){
char data[DATASEG_SZ];
int seq=parseData(datas,len,data);
// 建构数据结构体
dataSegment ds;
ds.seq=seq;
// cout<<"seq: "<<seq<<endl;
// cout<<"len-headlen: "<<(len-HEAD_LEN)<<endl;
// cout<<"strlen(data): "<<strlen(data)<<endl;
// cout<<"data: "<<data<<endl;
memcpy(ds.data,data,(len-HEAD_LEN));
// 计算该数据段的相对位置
int pos=seq-this->headSeq;
// cout<<"pos: "<<pos<<endl;
// 放入队列
this->setDataSegment(ds,pos);
}
void PriorQueue::setDataSegment(char* datas,int len){
const char* datas_temp=datas;
this->setDataSegment(datas_temp,len);
}
// 缓存数据段
void PriorQueue::setDataSegment(dataSegment ds,int pos){
// cout<<"count: "<<count<<endl;
// cout<<dataPriorQueue.size()<<endl;
this->dataPriorQueue[pos]=ds;
count++;
// cout<<"success set"<<endl;
}
// 如果数据包不满,则阻塞
// void PriorQueue::waitfull(){
// pthread_mutex_lock(&mutex) ;
// while(this->count<this->maxNum) {
// pthread_cond_wait(&full_cond , &mutex) ;
// }
// pthread_mutex_unlock(&mutex) ;
// };
// 判断该队列是否放满了数据
bool PriorQueue::isfull(){
return this->count==this->getMaxNum();
}
// 返回完整数据包
char* PriorQueue::getDataPacket(){
// cout<<"*********getDataPacket Information********"<<endl;
// cout<<"count: "<<count<<endl;
// cout<<"maxNum: "<<getMaxNum()<<endl;
// cout<<"headseq: "<<getHeadSeq()<<endl;
// cout<<"datatail: "<<getDataTail()<<endl;
// cout<<"datalen: "<<getDataLen()<<endl;
// cout<<"******************************************"<<endl;
// 如果数据包不满,则阻塞
// waitfull();
// char* dp[QUEUE_SZ];
char *dp;
dp=(char*)malloc(this->datalen*sizeof(char));
int rear=0;
int clen=DATASEG_SZ;
// 将数据段组合成数据包
int i=0;
for (i = 0; i < (this->maxNum-1);i++){
// 打印dataPriorQueue的状态
// cout<<"sizeof(datapq): "<<dataPriorQueue.size()<<endl;
// cout<<dataPriorQueue[i].data<<endl;
memcpy(&dp[rear],dataPriorQueue[i].data,clen);
rear+=clen;
}
if(this->dataTail!=0){
clen=this->dataTail;
}
memcpy(&dp[rear],dataPriorQueue[i].data,clen);
rear+=dataTail;
// 释放数据区内存
vector<dataSegment> vtemp;
this->dataPriorQueue.swap(vtemp);
// cout<<"sizeof(datapq): "<<dataPriorQueue.size()<<endl;
return dp;
}
@@ -0,0 +1,66 @@
#ifndef _PRIOR_QUEUE_H_
#define _PRIOR_QUEUE_H_
// 缓存同属于一个数据包的众多数据段的优先队列
#include<cstring>
#include<pthread.h>
#include<vector>
#define QUEUE_SZ 8000000 //数据包最大长度
#define DATASEG_SZ 8000 //数据段最大长度
#define HEAD_LEN 12 //数据段头长度
using namespace std;
// 定义数据段结构体
struct dataSegment{
unsigned int seq; //该数据段的序列号
char data[DATASEG_SZ]; //数据段信息
};
class PriorQueue{
public:
PriorQueue();
~PriorQueue();
// 参数存取区
void setHeadSeq(unsigned int seqFirst);
unsigned int getHeadSeq();
void setDataLen(unsigned int datalen);
unsigned int getDataLen();
void setMaxNum(int seq_n);
int getMaxNum();
void setDataTail(int dataTail);
int getDataTail();
// 将一个字符串解析,
// 并根据序号差将当前数据段放置在相应位置
void setDataSegment(char* datas,int len);
void setDataSegment(const char* datas,int len);
void setDataSegment(dataSegment ds,int pos);
// 等待所有数据段到达
void waitfull();
// 将所有数据段合并成数据包进行返回
char* getDataPacket();
// 判断该队列是否放满数据
bool isfull();
protected:
// 标记该队列当前存储的数据包的首序列号seq_first
unsigned int headSeq;
// 标记该数据包的总长度
unsigned int datalen;
//标记该队列的结构体最大个数/分包数目seq_n
int maxNum;
// 标记最后一个数据段的长度
int dataTail;
//标志已经存入的数据段个数
int count;
// 存储数据段结构体的容器(vector)
vector<dataSegment> dataPriorQueue;
// vector<int> dataPriorQueue;
// 数据锁:
// 对可能在线程之间读写冲突的共享数据进行加锁。
// pthread_cond_t full_cond ; //条件锁
// pthread_mutex_t mutex ; //互斥锁
private:
int parseData(const char* dataSeg,int len,char* rawdata);
};
#endif
@@ -0,0 +1,169 @@
#include<iostream>
#include "QueuePool.h"
using namespace std;
QueuePool::QueuePool(){
this->wantSeq=0;
this->flag_head=0;
// 初始化条件锁、互斥锁
// pthread_cond_init(&full_cond, NULL) ;
// pthread_mutex_init(&mutex , NULL) ;
}
QueuePool::~QueuePool(){
}
// 设置wantSeq
void QueuePool::setWantSeq(unsigned int wantSeq){
this->wantSeq=wantSeq;
}
// 设置wantSeq
void QueuePool::setWantSeq(unsigned int lastSeq,unsigned int seq_n){
this->wantSeq=(lastSeq+seq_n);
}
// 获取wantSeq
unsigned int QueuePool::getWantSeq(){
return this->wantSeq;
}
// 重置wantSeq
void QueuePool::initSelf(){
// pthread_mutex_lock(&m_mutex) ;
this->wantSeq=0;
// pthread_mutex_unlock(&m_mutex) ;
}
// 设置头部缓存队列
void QueuePool::setHeadQueue(PriorQueue pq){
this->headQueue=pq;
}
// 将头部缓存队列的数据弹出到二级缓存队列中
void QueuePool::moveDataPacket(){
if(this->flag_head==0){
cout<<"move data packet error."<<endl;
return;
}
char* dataPacket;
dataPacket=this->headQueue.getDataPacket();
unsigned int datalen=this->headQueue.getDataLen();
this->r_queue.push_ndata(dataPacket,(int)datalen);
// 更新want_seq、flag_head
int pkgn=this->headQueue.getMaxNum();
this->setWantSeq(wantSeq,(unsigned int)pkgn);
flag_head=0;
}
// 更新头部缓存队列
void QueuePool::updateHeadQueue(){
if(this->flag_head==1){
cout<<"update head queue error."<<endl;
return;
}
map<unsigned int,PriorQueue>::iterator it;
it=this->waitQueues.find(wantSeq);
if(it!=waitQueues.end()){
this->setHeadQueue((*it).second);
this->flag_head=1;
waitQueues.erase(it);
}else{}
}
// 往数据缓存池中放入一个数据段
void QueuePool::pushDataSegment(const char* data,int len){
// 取一个数据段的头序列号
unsigned int seq_first;
memcpy(&seq_first,&data[4],4);
// 匹配头部缓存队列
if((flag_head==1)&&(seq_first==this->headQueue.getHeadSeq())){
this->headQueue.setDataSegment(data,len);
// 若头部队列满了,则不断更新它
while((flag_head==1)&&(this->headQueue.isfull())){
this->moveDataPacket();
this->updateHeadQueue();
}
}else{
// 匹配一级缓存队列池
map<unsigned int,PriorQueue>::iterator it;
it=this->waitQueues.find(seq_first);
if(it!=waitQueues.end()){
(*it).second.setDataSegment(data,len);
}else{
// 该数据段是所属数据包到达的第一个数据段
PriorQueue pq;
pq.setDataSegment(data,len);
// 加到头部
if((flag_head==0)&&(wantSeq==seq_first)){
this->setHeadQueue(pq);
this->flag_head=1;
// 若头部队列满了,则不断更新它
while((flag_head==1)&&(this->headQueue.isfull())){
this->moveDataPacket();
this->updateHeadQueue();
}
}else{
//加到map中
// cout<<"insert the map"<<endl;
waitQueues.insert(map<unsigned int,PriorQueue>::value_type(pq.getHeadSeq(),pq));
}
}
}
// 打印数据缓存池的当前状态。测试用
// this->printQueuePool();
}
void QueuePool::pushDataSegment(char* data,int len){
const char* data_temp=data;
this->pushDataSegment(data_temp,len);
}
// 打印二级缓存队列的数据
void QueuePool::printRQueue(){
int n=this->r_queue.get_data_len();
char data[n];
this->r_queue.get_ndata(data,n);
// cout<<data<<endl;
if(n!=0){
cout<<"r_queue_data_len: "<<n<<endl;
cout<<"the r_queue data now is: ";
for(int i=0;i<n;i++){
cout<<data[i];
}
cout<<endl;
}else{
cout<<"the r_queue data now is null. "<<endl;
}
}
// 打印整个队列池的队列状态
void QueuePool::printQueuePool(){
// cout<<endl<<endl;
cout<<"*********The Queue Pool State Information********"<<endl;
cout<<"the wantSeq is: "<<this->getWantSeq()<<endl;
// 二级缓存队列
cout<<"--------------------------------------------------------------------"<<endl;
this->printRQueue();
// 头部等待队列
cout<<"--------------------------------------------------------------------"<<endl;
if(this->flag_head==0){
cout<<"the head queue of the first level queue is null."<<endl;
}else{
cout<<"the head queue's headSeq is: "
<<this->headQueue.getHeadSeq()
<<endl;
}
// 一级缓存队列池
cout<<"--------------------------------------------------------------------"<<endl;
cout<<"the first level queue map size is: "<<waitQueues.size()<<endl;
if(waitQueues.size()!=0){
map<unsigned int,PriorQueue>::iterator it;
cout<<"Their headSeq(s) are: ";
for(it=waitQueues.begin();it!=waitQueues.end();it++){
cout<<(*it).first<<" ";
}
cout<<endl;
}
cout<<"***************************************************"<<endl;
}
@@ -0,0 +1,59 @@
#ifndef _PRIOR_QUEUE_POOL_H_
#define _PRIOR_QUEUE_POOL_H_
// 解析数据段,存放数据段进序号优先队列
// 当要接收到的下一个数据包全部到达时,
// 将该队列的数据包缓存入顺序缓冲队列.
#include<string.h>
#include<pthread.h>
#include<map>
#include "PriorQueue.h"
#include "r_queue.h"
class QueuePool{
public:
QueuePool();
~QueuePool();
// 放入一个数据段
void pushDataSegment(const char *data,int len);
void pushDataSegment(char *data,int len);
// 更新头部缓存队列
void updateHeadQueue();
// 将某一级缓存队列设置成头部缓存队列
void setHeadQueue(PriorQueue pq);
// 弹出头部缓存队列的数据
void moveDataPacket();
// 重置wantSeq为0
void initSelf();
// 打印二级缓存队列的数据。用于测试
void printRQueue();
// 打印当前QueuePool的状态信息。用于测试
void printQueuePool();
public:
// 二级缓存队列。能够直接读取数据的缓存区
R_Queue r_queue;
protected:
// 当前想要拿到的数据包的首序列号
unsigned int wantSeq;
// 头部缓存队列是否为空的标志
int flag_head;
//头部缓存队列(headSeq等于want_seq的一级缓存队列)
PriorQueue headQueue;
// 一级缓存队列池
map<unsigned int,PriorQueue> waitQueues;
// 数据锁
// pthread_cond_t _cond ; //条件锁
// pthread_mutex_t _mutex ; //互斥锁
private:
void setWantSeq(unsigned int wantSeq);
void setWantSeq(unsigned int lastSeq, unsigned int seq_n);
unsigned int getWantSeq();
};
// 设置头部缓存队列的目的是:
// 只要它满了,就可以弹出数据到二级缓存,
// 而不需要每次在队列池先找到want_seq,再判断
#endif
Binary file not shown.
@@ -0,0 +1,23 @@
testMain: testMain.o QueuePool.o PriorQueue.o r_queue.o
g++ -o testMain testMain.o QueuePool.o PriorQueue.o r_queue.o
testMain.o : testMain.cpp
g++ -c -g testMain.cpp
QueuePool.o: QueuePool.cpp QueuePool.h
g++ -c -g QueuePool.cpp
PriorQueue.o : PriorQueue.cpp PriorQueue.h
g++ -c -g PriorQueue.cpp
r_queue.o: r_queue.cpp r_queue.h
g++ -c -g r_queue.cpp
clean :
rm -rf *.o testMain
# testMain: PriorQueue.o testMain.o
# g++ -o testMain PriorQueue.o testMain.o
# PriorQueue.o : PriorQueue.cpp PriorQueue.h
# g++ -c PriorQueue.cpp
# testMain.o : testMain.cpp
# g++ -c testMain.cpp
# clean :
# rm -rf *.o testMain
@@ -0,0 +1,164 @@
#include <iostream>
#include "r_queue.h"
using namespace std;
R_Queue::R_Queue(){
this->head = 0 ;
this->rear = 0 ;
pthread_cond_init(&has_data , NULL) ;
pthread_cond_init(&has_space , NULL) ;
pthread_mutex_init(&m_mutex , NULL) ;
}
R_Queue::~R_Queue(){
}
int R_Queue::get_head(){
int ret = 0 ;
pthread_mutex_lock(&m_mutex) ;
ret = head ;
pthread_mutex_unlock(&m_mutex) ;
return head ;
}
int R_Queue::get_rear(){
return rear ;
}
bool R_Queue::is_full(){
return ((this->rear+1)%QUEUE_SZ == this->head) ;
}
bool R_Queue::is_empty(){
bool ret = false ;
pthread_mutex_lock(&m_mutex) ;
ret = (this->head == this->rear) ;
pthread_mutex_unlock(&m_mutex) ;
return ret ;
}
char *R_Queue::get_head_p(){
return &(buff[this->head]);
}
char *R_Queue::get_rear_p(){
return &(buff[this->rear]) ;
}
// 得到所有数据的长度
int R_Queue::get_data_len(){
int ret = 0 ;
pthread_mutex_lock(&m_mutex) ;
ret = (rear - head + QUEUE_SZ)%QUEUE_SZ ;
pthread_mutex_unlock(&m_mutex) ;
return ret ;
}
// 得到空余长度
int R_Queue::get_free_space(){
return (head-rear-1+QUEUE_SZ)%QUEUE_SZ ;
}
// get the length of a continuous free space
// 获得从rear开始往后的连续剩余空间的长度
int R_Queue::get_cfree_space(){
int space = 0 ;
if(head <= rear ) {
space = QUEUE_SZ - rear ;
if(head == 0) {
space -= 1 ;
}
}else{
space = head - rear - 1 ;
}
return space ;
}
// begin at head , get the continuous data block len in ring queue
// 获得从head往后的连续数据段的长度
int R_Queue::get_cdata_len(){
int len = 0;
if(rear < head){
len = QUEUE_SZ - head ;
}else{
len = rear-head ;
}
return len ;
}
// 增加n字节的数据
// 如果是从空到有,则激活has_data条件锁
int R_Queue::add_n(int n){
bool need_signal = false ;
pthread_mutex_lock(&m_mutex) ;
need_signal = (head == rear) ;
rear = (rear + n) % QUEUE_SZ ;
pthread_mutex_unlock(&m_mutex) ;
if(need_signal){
pthread_cond_signal(&has_data) ;
}
}
// 减少n字节的数据
// 如果是从满到不满,则激活has_space条件锁
int R_Queue::rmv_n(int n){
bool need_signal = false ;
pthread_mutex_lock(&m_mutex) ;
need_signal = ((rear+1)%QUEUE_SZ == head) ;
head = (head + n) % QUEUE_SZ ;
pthread_mutex_unlock(&m_mutex) ;
if(need_signal){
pthread_cond_signal(&has_space) ;
}
}
// copy n Byte data from buff to data
// 从start开始,往后取n字节数据
int R_Queue::get_ndata(int start , char *data ,int n ){
//printf("&&&&&&&&&&&& = start = %d , n = %d \n",start , n );
if(start + n >= QUEUE_SZ){
memcpy(data,&buff[start],QUEUE_SZ-start);
memcpy(&data[QUEUE_SZ-start],buff,n+start-QUEUE_SZ);
}else{
memcpy(data,&buff[start],n);
}
}
// copy n Byte data from buff to data
// 从head开始,往后取n字节数据
int R_Queue::get_ndata(char *data ,int n ){
get_ndata(head , data , n) ;
}
// 队列中加入n字节数据
int R_Queue::push_ndata(const char *data , int n){
//if(get_free_space() < n) return -1 ;
while(get_free_space() < n ) ;
int clen ;
while(n > 0){
clen = get_cfree_space() ;
if(clen > n) clen = n;
memcpy(&buff[rear],data,clen);
add_n(clen);
n -= clen ;
}
return 0;
}
// 等待数据,若队列为空,当前进程等待在 has_data变量下
void R_Queue::wait4data() {
pthread_mutex_lock(&m_mutex) ;
while(head == rear) {
pthread_cond_wait(&has_data , &m_mutex) ;
}
pthread_mutex_unlock(&m_mutex) ;
}
// 等待空余,若队列为满,当前进程等待在has_space变量下
void R_Queue::wait4space() {
pthread_mutex_lock(&m_mutex) ;
while( (rear+1)%QUEUE_SZ == head) {
pthread_cond_wait(&has_space , &m_mutex) ;
}
pthread_mutex_unlock(&m_mutex) ;
}
@@ -0,0 +1,60 @@
#ifndef _R_QUEUE_H_
#define _R_QUEUE_H_
// 针对数据包已按照发送顺序缓存得到的数据队列
#include <string.h>
#include <pthread.h>
#define QUEUE_SZ 8000000 //约8MB
class R_Queue
{
public:
R_Queue() ;
~R_Queue();
int get_head();
int get_rear();
bool is_full();
bool is_empty();
int add_n(int n);
int rmv_n(int n);
char *get_head_p();
char *get_rear_p();
// 得到所有数据的长度;
int get_data_len();
// begin at head , get the continuous data block len in ring queue;
int get_cdata_len();
// 得到空余长度;
int get_free_space();
// get the length of a continuous free space;
int get_cfree_space();
// copy n Byte data from buff to data ;
// 从start开始,往后取n字节数据;
int get_ndata(int start , char *data ,int n );
int get_ndata(char *data ,int n );
// 队列中加入n字节数据;
int push_ndata(const char *data , int n);
// int push_ndata(const char *data , unsigned int n);
// 等待数据,若队列为空,当前进程等待在 has_data变量下
void wait4data() ;
void wait4space() ;
protected:
int rear ;
int head ;
char buff[QUEUE_SZ];
pthread_cond_t has_data ; //条件锁
pthread_cond_t has_space ;
pthread_mutex_t m_mutex ; //互斥锁
private:
/* data */
};
#endif
Binary file not shown.
@@ -0,0 +1,157 @@
#include<iostream>
#include<stdlib.h>
#include<cstring>
#include "QueuePool.h"
#define HEAD_LEN 12
// #define DATASEG_SZ 20 //数据段最大长度
using namespace std;
// 测试程序
// 用于测试QueuePool对于数据段乱序的处理
// 将字符数组封装成约定格式的数据段
int makeData(unsigned int seq,unsigned int seq_first,
unsigned int len,char *data,int datalen,char *resultData);
int main(){
// 制造数据包0:包含数据段012
char rawData0[]="imissyou.00000.";
char rawData1[]="imissyou.11111.";
char rawData2[]="imissyou.2222.";
char resultData0[15+HEAD_LEN];
char resultData1[15+HEAD_LEN];
char resultData2[14+HEAD_LEN];
makeData(0,0,44,rawData0,15,resultData0);
makeData(1,0,44,rawData1,15,resultData1);
makeData(2,0,44,rawData2,14,resultData2);
// 制造数据包3:包含数据段345
char rawData3[]="imissyou.33333.";
char rawData4[]="imissyou.44444.";
char rawData5[]="imissyou.555.";
char resultData3[15+HEAD_LEN];
char resultData4[15+HEAD_LEN];
char resultData5[13+HEAD_LEN];
makeData(3,3,43,rawData3,15,resultData3);
makeData(4,3,43,rawData4,15,resultData4);
makeData(5,3,43,rawData5,13,resultData5);
// 新建并打印QueuePool的初始状态
QueuePool *qp= new QueuePool();
qp->printQueuePool();
// 按照序号420351的顺序模拟乱序数据段的接收
// 注:此时数据段的先后顺序不仅包内乱序,
// 而且包间乱序
cout<<endl<<endl;
cout<<"set data segment 4 of data packet 3: "<<endl;
qp->pushDataSegment(resultData4,15+HEAD_LEN);
cout<<endl<<endl;
cout<<"set data segment 2 of data packet 0: "<<endl;
qp->pushDataSegment(resultData2,14+HEAD_LEN);
cout<<endl<<endl;
cout<<"set data segment 0 of data packet 0: "<<endl;
qp->pushDataSegment(resultData0,15+HEAD_LEN);
cout<<endl<<endl;
cout<<"set data segment 3 of data packet 3: "<<endl;
qp->pushDataSegment(resultData3,15+HEAD_LEN);
cout<<endl<<endl;
cout<<"set data segment 5 of data packet 3: "<<endl;
qp->pushDataSegment(resultData5,13+HEAD_LEN);
cout<<endl<<endl;
cout<<"set data segment 1 of data packet 0: "<<endl;
qp->pushDataSegment(resultData1,15+HEAD_LEN);
delete qp;
return 0;
}
// 将数据加上首序列号等信息
int makeData(unsigned int seq,unsigned int seq_first,
unsigned int len,char *data,int datalen,char *resultData){
memcpy(&resultData[0],&seq,4);
memcpy(&resultData[4],&seq_first,4);
memcpy(&resultData[8],&len,4);
memcpy(&resultData[12],&data[0],datalen);
return 0;
}
// int main(){
// PriorQueue *pq= new PriorQueue();
// char rawData1[]="imissyou.11111.";
// char rawData2[]="imissyou.22222.";
// char rawData3[]="imissyou.33333.";
// char resultData1[8000+HEAD_LEN];
// char resultData2[8000+HEAD_LEN];
// char resultData3[7000+HEAD_LEN];
// makeData(0,0,23000,rawData1,8000,resultData1);
// makeData(1,0,23000,rawData2,8000,resultData2);
// makeData(2,0,23000,rawData3,7000,resultData3);
// cout<<endl<<endl<<endl;
// cout<<"test2"<<endl;
// pq->setDataSegment(resultData2,8012);
// cout<<endl<<endl<<endl;
// cout<<"test1"<<endl;
// pq->setDataSegment(resultData1,8012);
// cout<<endl<<endl<<endl;
// cout<<"test3"<<endl;
// pq->setDataSegment(resultData3,7012);
// char *dataPacket;
// cout<<endl<<endl<<endl;
// dataPacket=pq->getDataPacket();
// cout<<endl<<endl<<endl;
// cout<<"dataPacket: "<<endl;
// cout<<dataPacket<<endl;
// cout<<&dataPacket[8000]<<endl;
// cout<<&dataPacket[16000]<<endl;
// delete pq;
// return 0;
// }
// int main(){
// // 制造数据段区
// PriorQueue *pq= new PriorQueue();
// char rawData1[]="imissyou.11111.";
// char rawData2[]="imissyou.22222.";
// char rawData3[]="imissyou.3333.";
// char resultData1[15+HEAD_LEN];
// char resultData2[15+HEAD_LEN];
// char resultData3[14+HEAD_LEN];
// makeData(0,0,44,rawData1,15,resultData1);
// makeData(1,0,44,rawData2,15,resultData2);
// makeData(2,0,44,rawData3,14,resultData3);
// // 装填数据段区
// cout<<endl<<endl<<endl;
// cout<<"test2"<<endl;
// pq->setDataSegment(resultData2,15+HEAD_LEN);
// cout<<endl<<endl<<endl;
// cout<<"test1"<<endl;
// pq->setDataSegment(resultData1,15+HEAD_LEN);
// cout<<endl<<endl<<endl;
// cout<<"test3"<<endl;
// pq->setDataSegment(resultData3,14+HEAD_LEN);
// // 组装数据包区
// char *dataPacket;
// cout<<endl<<endl<<endl;
// dataPacket=pq->getDataPacket();
// cout<<endl<<endl<<endl;
// cout<<"dataPacket: "<<endl;
// cout<<dataPacket<<endl;
// delete pq;
// return 0;
// }
+36
View File
@@ -0,0 +1,36 @@
LFLAGS := -lpthread -lpcap -lndn-cxx -lboost_system -ljsoncpp
main: send recv1 recv2
send : ndnp2p_send.o ndn_socket.o QueuePool.o PriorQueue.o r_queue.o
g++ -o send ndnp2p_send.o ndn_socket.o QueuePool.o PriorQueue.o r_queue.o $(LFLAGS)
recv1 : ndnp2p_recv1.o ndn_socket.o QueuePool.o PriorQueue.o r_queue.o
g++ -o recv1 ndnp2p_recv1.o ndn_socket.o QueuePool.o PriorQueue.o r_queue.o $(LFLAGS)
recv2 : ndnp2p_recv2.o ndn_socket.o QueuePool.o PriorQueue.o r_queue.o
g++ -o recv2 ndnp2p_recv2.o ndn_socket.o QueuePool.o PriorQueue.o r_queue.o $(LFLAGS)
ndnp2p_recv1.o : ndnp2p_recv1.cpp
g++ -c -g -std=c++14 ndnp2p_recv1.cpp
ndnp2p_recv2.o : ndnp2p_recv2.cpp
g++ -c -g -std=c++14 ndnp2p_recv2.cpp
ndnp2p_send.o : ndnp2p_send.cpp
g++ -c -g -std=c++14 ndnp2p_send.cpp
ndn_socket.o : ndn_socket.cpp ndn_socket.h
g++ -c -g -std=c++14 ndn_socket.cpp
QueuePool.o: PriorQueuePool/QueuePool.cpp PriorQueuePool/QueuePool.h
g++ -c -g -std=c++14 PriorQueuePool/QueuePool.cpp
PriorQueue.o : PriorQueuePool/PriorQueue.cpp PriorQueuePool/PriorQueue.h
g++ -c -g -std=c++14 PriorQueuePool/PriorQueue.cpp
r_queue.o : PriorQueuePool/r_queue.cpp PriorQueuePool/r_queue.h
g++ -c -g -std=c++14 PriorQueuePool/r_queue.cpp
clean :
rm -rf *.o send recv1 recv2
+346
View File
@@ -0,0 +1,346 @@
#include <iostream>
#include "ndn_socket.h"
using namespace std;
using namespace ndn;
// 类的实例化
Ndn_socket::Ndn_socket(){
this->seq = 0 ;
this->faddr = "ini_faddr";
this->daddr = "ini_daddr";
// 时间戳
struct timeval start ;
gettimeofday(&start , NULL) ;
this->start_ts = to_string(start.tv_sec) ;
pthread_create(&(this->m_tid) , NULL , run, (void*)&m_face) ;
this->state = true ;
}
Ndn_socket::~Ndn_socket(){
}
// 设置某特定prefix的兴趣监听
int Ndn_socket::listen(const char *prefix){
this->maddr = prefix ;
//cout << "set filter " << prefix << endl ;
m_face.setInterestFilter(prefix,
bind(&Ndn_socket::onInterest, this, _1, _2) ,
RegisterPrefixSuccessCallback() ,
bind(&Ndn_socket::onRegisterFailed, this, _1, _2)) ;
return 0 ;
}
// 设置要将数据推送到的目的prefix
int Ndn_socket::set_daddr(const char * prefix){
if(prefix!=this->daddr){
// 向新的ndn_socket发送数据
// 重置seq
this->seq=0;
// 重置start_ts => 保证后续数据名的唯一性
// 长度无限增长是个bug,后期可优化
this->start_ts = (this->start_ts+'0' );
}
this->daddr = prefix ;
return 0 ;
}
// 查询要将数据推送到的目的prefix
string Ndn_socket::get_daddr(){
return this->daddr ;
}
int Ndn_socket::write(const string& data) {
return this->write(data.data() , data.length() , this->maddr) ;
}
int Ndn_socket::write(const char * data , int len ) {
return this->write(data , len , this->maddr) ;
}
int Ndn_socket::write(const uint8_t * data , int len) {
return this->write((char*)data, len , this->maddr) ;
}
int Ndn_socket::write(const uint8_t * data , int len , string dname_base) {
return this->write((char*)data, len , dname_base) ;
}
// 给数据段加段头
int Ndn_socket::makeData(unsigned int seq,unsigned int seq_first,
unsigned int len,const char *data,int datalen,char *resultData){
memcpy(&resultData[0],&seq,4);
memcpy(&resultData[4],&seq_first,4);
memcpy(&resultData[8],&len,4);
memcpy(&resultData[12],&data[0],datalen);
return 0;
}
// 解析数据段=>用于测试
int Ndn_socket::parseData(char* dataSeg,int datalen,char* rawdata){
unsigned int seq;
unsigned int seq_first;
unsigned int len;
// cout<<"szof(dataSeg): "<<sizeof(dataSeg)<<endl;
// cout<<"strlen(dataSeg): "<<strlen(dataSeg)<<endl;
cout<<"**********the parse result is: ***********"<<endl;
// char* data=(char*)malloc((datalen-HEAD_LEN)*sizeof(char));
memcpy(&seq,&dataSeg[0],4);
cout<<"seq: "<<seq<<endl;
memcpy(&seq_first,&dataSeg[4],4);
cout<<"seq_first: "<<seq_first<<endl;
memcpy(&len,&dataSeg[8],4);
cout<<"len: "<<len<<endl;
memcpy(rawdata,&dataSeg[12],(datalen-HEAD_LEN));
cout<<"rawdata: "<<rawdata<<endl;
cout<<"***************************************"<<endl;
return 0;
}
// brief : 往ndn_socket中写入数据
// param : data 数据
// len 数据长度
// dname_base 数据包的前缀名称
int Ndn_socket::write(const char * data , int len , string dname_base ) {
// 给本机前缀加一个start_ts命名段
if(dname_base[dname_base.length()-1] != '/') {
dname_base += ("/"+this->start_ts+"/") ;
}
// 计算拆分成的数据段的数目
int pkt_n = len/DATASEG_SZ;
if(len%DATASEG_SZ != 0) {
pkt_n ++ ;
}
// 给本机前缀加一个start_ts命名段、一个seq、一个"-seq+pkt_n""
// 用以附加在Block中传递给目的主机
string pre_payload = dname_base + to_string(seq) + "-" + to_string(seq+pkt_n) ;
// 记录该数据包的第一个数据段的seq
unsigned int seq_first=seq;
// 依次将分割出的每段数据放入face中
for (int i = 0; i < pkt_n; i++) {
Data data_pkt ;
// 设置数据名字(“本机字段+start_ts+seq”)
data_pkt.setName(dname_base + to_string(seq)) ;
// cout<<"data_pkt_name: "<<dname_base + to_string(seq)<<endl;
// c_len,当前数据段的长度
int c_len = DATASEG_SZ ;
if(len - i*DATASEG_SZ < DATASEG_SZ) {
c_len = len - i*DATASEG_SZ ;
}
// 加段头
// cout<<"c_len: "<<c_len<<endl;
char resultData[c_len+HEAD_LEN];
this->makeData(seq,seq_first,(unsigned int)len,data+i*DATASEG_SZ,c_len,resultData);
char rawdata[c_len];
// this->parseData(resultData,c_len+HEAD_LEN,rawdata);
// 设置数据内容:这里需要修改数据格式,加一个头部
data_pkt.setContent(reinterpret_cast<const uint8_t*>(resultData), c_len+HEAD_LEN) ;
// data_pkt.setContent(reinterpret_cast<const uint8_t*>(data+i*DATASEG_SZ), c_len) ;
//...
this->m_keyChain.sign(data_pkt) ;
//...
this->m_face.put(data_pkt) ;
// seq顺序递增
seq ++ ;
}
// 给目的地前缀加一个start_ts命名段、一个seq,用以设置目的兴趣包的包名
string pre_iname = daddr +"/"+ this->start_ts + "/" + to_string(seq) ;
// 设置interest
Interest pre_int(Name(pre_iname.data())) ;
// cout<<"pre_interest name: "<<pre_iname<<endl;
pre_int.setInterestLifetime(1_s) ;
pre_int.setMustBeFresh(true) ;
Block app_param = makeBinaryBlock(tlv::AppPrivateBlock1+1,
pre_payload.data(), pre_payload.length());
pre_int.setParameters(app_param) ;
// 发送预请求兴趣包
this->m_face.expressInterest(pre_int ,
bind(&Ndn_socket::onData_pre,this,_1,_2),
bind(&Ndn_socket::onNack_pre,this,_1,_2),
bind(&Ndn_socket::onTimeout_pre,this,_1));
//cout << "pre I>> : " << pre_int.getName() << endl;
return len ;
}
// 接收数据(从队列取出,放入data)
int Ndn_socket::read(char *data , int buf_sz) {
qp.r_queue.wait4data() ;
if(this->state == false) {
return -1 ;
}
//获取队列中的数据长度
//(队列中数据较多,则按照read函数的参数取数据)
int data_len = qp.r_queue.get_data_len() ;
if(data_len > buf_sz) {
data_len = buf_sz ;
}
// 拿到数据
qp.r_queue.get_ndata(data , data_len) ;
qp.r_queue.rmv_n(data_len) ;
// 返回实际拿到的数据长度
return data_len ;
}
// 关闭face
// 1. 不需要关闭线程m_tid吗?=> 直接关闭开ndn_socket的这个进程,也一样效果
// 2. 为何要r_queue.push_ndata(&c_flag,1) ;???=> 让这个队列的waitdata()不阻塞
// 用来给read()函数返回一个-1,而不是无限循环等待。
int Ndn_socket::close(){
if(this->state == false ) {
return 0 ;
}
this->state = false ;
char c_flag = 'c' ;
qp.r_queue.push_ndata(&c_flag,1) ;
// 等待兴趣包完全被处理,就关掉face
while(m_face.getNPendingInterests() > 0){
usleep(10000) ;
}
this->m_face.shutdown() ;
return 0 ;
}
// 开启face
void *Ndn_socket::run(void *param){
Face *face_p = (Face*)param ;
face_p->processEvents(time::milliseconds::zero(), true) ;
}
// -----------------------NDN中的常见函数-----------------------
void Ndn_socket::onInterest(const InterestFilter& filter,
const Interest& interest) {
//cout << "onInterest : " << interest.getName() << endl ;
if(interest.hasParameters()){
uint8_t p_type = 0 ;
// 为何不是“memcpy(&p_type , interest.getParameters().type() , 1) ;”?
// 不是要取Block的Type吗??这里可以进一步探究尝试。
memcpy(&p_type , interest.getParameters().value() , 1) ;
// memcpy(&p_type , interest.getParameters().type() , 1) ;
if(p_type == tlv::AppPrivateBlock1 + 1) { // 预请求包
// 取Block
Block dname_block(interest.getParameters().value() ,
interest.getParameters().value_size()) ;
// 取Block的数值
string datas_name((char*)dname_block.value() ,
dname_block.value_size()) ;
// cout << "datas_name : " <<datas_name << endl ;
// format : /ndn/edu/pkusz/node11/vpn/5-9
// 拿到seq以及seq+pkt_n
int idx1 = datas_name.rfind('/')+1 ;
int first, last ;
sscanf(datas_name.data()+idx1 , "%d-%d" , &first , &last) ;
string iname_base = datas_name.substr(0, idx1) ;
// 判断是否更换了新的ndn_sockt
if(iname_base!=this->faddr){
qp.initSelf();
this->faddr=iname_base;
}
// 依次请求该条信息的每个数据段
//(数据产生者的前缀隐藏在Block中)
for (int i = first; i < last; i++) {
string interest_name = iname_base+ std::to_string(i) ;
// cout<<"data interest name: "<<interest_name<<endl;
Interest request_int(Name(interest_name.data())) ;
request_int.setInterestLifetime(1_s) ;
this->m_face.expressInterest(request_int ,
bind(&Ndn_socket::onData,this,_1,_2),
bind(&Ndn_socket::onNack,this,_1,_2),
bind(&Ndn_socket::onTimeout,this,_1));
//cout << "I>> : " << request_int.getName() << endl ;
}
}
}
}
// 发送兴趣包请求到的数据立即放入缓存队列
void Ndn_socket::onData(const Interest& interest , const Data& data){
int data_sz = data.getContent().value_size() ;
// cout<<"data_sz: "<<data_sz<<endl;
// r_queue.push_ndata(reinterpret_cast<const char*>(data.getContent().value()),
// data_sz) ;
qp.pushDataSegment(reinterpret_cast<const char*>(data.getContent().value()),
data_sz);
//cout << "D<< :" << data.getName() << " sz = " << data_sz << endl ;
}
// 预请求兴趣包的onData
void Ndn_socket::onData_pre(const Interest& interest , const Data& data){
//cout << "pre D<< :" << data.getName() << " sz = " <<
//data.getContent().value_size() << endl ;
}
void Ndn_socket::onNack(const Interest& interest, const Nack& nack){
cout << "Nack : "<< interest.getName() << endl ;
long lifetime = interest.getInterestLifetime().count() ;
if(lifetime > 3000) return ;
if(this->state == false) return ;
sleep(1) ;
Interest interest_new(interest.getName());
interest_new.setMustBeFresh(true) ;
boost::chrono::milliseconds new_lifetime(lifetime+200) ;
interest_new.setInterestLifetime(new_lifetime);
this->m_face.expressInterest(interest_new,
bind(&Ndn_socket::onData,this,_1,_2),
bind(&Ndn_socket::onNack,this,_1,_2),
bind(&Ndn_socket::onTimeout,this,_1));
cout << "I>> : " << interest_new.getName() << endl ;
//this->m_face.shutdown() ;
}
// 预请求兴趣包的onNack
void Ndn_socket::onNack_pre(const Interest& interest, const Nack& nack){
cout << "pre Nack : "<< interest.getName() << endl ;
cout << "listen : " << this->maddr << endl ;
long lifetime = interest.getInterestLifetime().count() ;
if(lifetime > 3000 || this->state == false ) return ;
sleep(1) ;
Interest interest_new(interest.getName());
interest_new.setMustBeFresh(true) ;
boost::chrono::milliseconds new_lifetime(lifetime+200) ;
interest_new.setInterestLifetime(new_lifetime);
interest_new.setParameters(interest.getParameters());
this->m_face.expressInterest(interest_new,
bind(&Ndn_socket::onData_pre,this,_1,_2),
bind(&Ndn_socket::onNack_pre,this,_1,_2),
bind(&Ndn_socket::onTimeout_pre,this,_1));
cout << "pre I>> : " << interest_new.getName() << endl ;
}
void Ndn_socket::onTimeout(const Interest& interest) {
cout << "Time out " << interest.getName() << endl ;
long lifetime = interest.getInterestLifetime().count() ;
if(lifetime > 3000) return ;
if(this->state == false) return ;
Interest interest_new(interest.getName());
boost::chrono::milliseconds new_lifetime(lifetime+200) ;
interest_new.setInterestLifetime(new_lifetime);
this->m_face.expressInterest(interest_new,
bind(&Ndn_socket::onData,this,_1,_2),
bind(&Ndn_socket::onNack,this,_1,_2),
bind(&Ndn_socket::onTimeout,this,_1));
}
// 预请求兴趣包的onTimeout
void Ndn_socket::onTimeout_pre(const Interest& interest) {
}
// face注册时,注册失败的提示信息
void Ndn_socket::onRegisterFailed(const Name& prefix, const std::string& reason)
{
std::cerr << "ERROR: Failed to register prefix \""
<< prefix << "\" in local hub's daemon (" << reason << ")"
<< std::endl;
m_face.shutdown();
}
+86
View File
@@ -0,0 +1,86 @@
#ifndef _NDN_SOCKET_H_
#define _NDN_SOCKET_H_
// 功能 : 启动一个face,并往固定的前缀发送数据
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <ndn-cxx/face.hpp>
#include <errno.h>
#include <exception>
#include "PriorQueuePool/QueuePool.h"
#include <sys/time.h>
#define HEAD_LEN 12 //数据段头部长度
#define DATASEG_SZ 8000 //最大数据段长度
using std::string ;
using ndn::Face ;
using ndn::KeyChain ;
using ndn::Interest ;
using ndn::InterestFilter ;
using ndn::Data ;
using ndn::Name ;
using ndn::lp::Nack ;
class Ndn_socket
{
public:
Ndn_socket();
~Ndn_socket();
int listen(const char * prefix) ; // 监听一个前缀
int set_daddr(const char * prefix) ; // 设置一个目标地址
string get_daddr() ;
// 发送数据
int write(const string & data) ;
int write(const char * data , int len) ;
int write(const char * data , int len , string dname_base) ;
int write(const uint8_t * data , int len) ;
int write(const uint8_t * data , int len , string dname_base) ;
// 接收数据
int read(char *data , int buf_sz) ;
//int read(char *data ) ;
int close() ; // 关闭线程-processEvent
private:
void onInterest(const InterestFilter& filter, const Interest& interest) ;
void onData(const Interest& interest , const Data& data);
void onData_pre(const Interest& interest , const Data& data);
void onNack(const Interest& interest, const Nack& nack);
void onNack_pre(const Interest& interest, const Nack& nack);
void onTimeout(const Interest& interest) ;
void onTimeout_pre(const Interest& interest) ;
void onRegisterFailed(const Name& prefix, const std::string& reason) ;
static void *run(void *param) ;
// 给数据段加段头
int makeData(unsigned int seq,unsigned int seq_first,
unsigned int len,const char *data,int datalen,char *resultData);
// 解析数据段=>用于测试
int parseData(char* dataSeg,int datalen,char* rawdata);
private:
/* data */
pthread_t m_tid ;
string maddr ; // 本机的地址
string daddr ; // 推送数据到的目的地址
string faddr ; //当前接收的数据段的源地址
unsigned int seq ;//切割后数据段的序列号
QueuePool qp; //二级队列缓存数据
string start_ts ; //时间戳
bool state ; //m_face是否注册成功的标志
Face m_face ; //数据收发接口
KeyChain m_keyChain ; //
};
#endif
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
#ifndef _NDNP2P_RECV_H_
#define _NDNP2P_RECV_H_
#endif
@@ -0,0 +1,28 @@
#include <iostream>
#include "ndn_socket.h"
#define BUFF_SZ 500
using namespace std;
int main()
{
Ndn_socket ndn_socket;
ndn_socket.listen("/localhost/nfd/recv1") ;
char buff[BUFF_SZ];
int read_n = 0 ; //收到的数据总长度
int recv_count = 0 ;
while((read_n = ndn_socket.read(buff,BUFF_SZ)) > 0){
cout << "count = " << ++recv_count << endl ;
cout<<"recv buff: ";
for(int x=0;x<BUFF_SZ;x++){
cout<<buff[x];
}
cout<<endl;
cout << "recv len = " << read_n << endl ;
cout<<endl;
// cout<<endl<<endl<<endl<<endl;
}
return 0;
}
@@ -0,0 +1,28 @@
#include <iostream>
#include "ndn_socket.h"
#define BUFF_SZ 500
using namespace std;
int main()
{
Ndn_socket ndn_socket;
ndn_socket.listen("/localhost/nfd/recv2") ;
char buff[BUFF_SZ];
int read_n = 0 ; //收到的数据总长度
int recv_count = 0 ;
while((read_n = ndn_socket.read(buff,BUFF_SZ)) > 0){
cout << "count = " << ++recv_count << endl ;
cout<<"recv buff: ";
for(int x=0;x<BUFF_SZ;x++){
cout<<buff[x];
}
cout<<endl;
cout << "recv len = " << read_n << endl ;
cout<<endl;
// cout<<endl<<endl<<endl<<endl;
}
return 0;
}
+39
View File
@@ -0,0 +1,39 @@
#include <iostream>
#include "ndn_socket.h"
#define BUFF_SZ 500
using namespace std;
int main()
{
Ndn_socket ndn_socket ;
ndn_socket.listen("/localhost/nfd/send") ;
char buff[BUFF_SZ] ;
ndn_socket.set_daddr("/localhost/nfd/recv1") ;
for (int i = 0; i < 5; i++) {
memset(buff, 'a'+i , BUFF_SZ) ;
ndn_socket.write(buff , BUFF_SZ) ;
cout<<"send buff: ";
for(int x=0;x<BUFF_SZ;x++){
cout<<buff[x];
}
cout<<endl;
cout<<endl;
}
ndn_socket.set_daddr("/localhost/nfd/recv2") ;
for (int i = 5; i < 10; i++) {
memset(buff, 'a'+i , BUFF_SZ) ;
ndn_socket.write(buff , BUFF_SZ) ;
cout<<"send buff: ";
for(int x=0;x<BUFF_SZ;x++){
cout<<buff[x];
}
cout<<endl;
cout<<endl;
}
ndn_socket.close() ;
return 0;
}
+4
View File
@@ -0,0 +1,4 @@
#ifndef _NDNP2P_SEND_H_
#define _NDNP2P_SEND_H_
#endif
+175
View File
@@ -0,0 +1,175 @@
// simulate socks5-client. coding by wefree in 2019.08
#include "Client.h"
using namespace std;
// listen to the local port
void Client::listenLocal(){
this->sockfd=socket(AF_INET, SOCK_STREAM, 0);
/* bind the local address, so that the cliend can send to server */
bzero((char *)&(this->serv_addr), sizeof(this->serv_addr));
(this->serv_addr).sin_family = AF_INET;
(this->serv_addr).sin_addr.s_addr = htonl(INADDR_ANY);
(this->serv_addr).sin_port = htons(this->port);
// bind
int on = 1;
setsockopt(this->sockfd , SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) ;
while( bind(this->sockfd, (struct sockaddr *) &(this->serv_addr), sizeof(this->serv_addr)) < 0){
sleep(1) ;
cout << "bind fail" << endl ;
};
listen(this->sockfd,10);
};
// listen to the local port
void Client::ndn_listen_local(string prefix){
this->listenLocal() ;
this->mndn_socket.listen(prefix.data()) ;
}
// waiting for the local port's connection
int Client::acceptLocal(){
int newsockfd;
struct sockaddr_in cli_addr;
int cli_len=sizeof(cli_addr);
cout<<"Waitting connection [client] ..."<<endl;
newsockfd = accept(this->sockfd, (struct sockaddr *) &cli_addr,
(socklen_t *)&cli_len);
// error
while(newsockfd<0){
cout<<"can't accept from local address"<<endl;
close(this->sockfd);
this->listenLocal();
newsockfd = accept(this->sockfd, (struct sockaddr *) &cli_addr,
(socklen_t *)&cli_len);
}
cout<<"Acceptted a connection [client]"<<endl;
return newsockfd;
};
// connect to the socks5-server
void Client::ndn_connSockes5Server(Ndn_socket &ndn_socket , string new_prefix){
cout << "new_prefix : " << new_prefix << endl ;
// 发送client_prefix
ndn_socket.write(new_prefix) ;
char buff[1000] ;
memset(buff, 0 , 1000) ;
// 接收server_prefix
ndn_socket.read(buff,1000) ;
string server_prefix=buff;
cout<<"server_prefix: "<<server_prefix<<endl;
ndn_socket.set_daddr(buff) ;
cout << "new client ndnsocket's daddr :" << ndn_socket.get_daddr() << endl ;
}
// data transmission shake
void Client::ndn_transData(Ndn_socket &ndn_socket , int newsockfd){
printf("Data transmission is beginning.\n");
// cout << "newsockfd's daddr :" << ndn_socket.get_daddr() << endl ;
void* sockfds[2] = {&ndn_socket,&newsockfd};
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);
ndn_socket.close() ;
// exit the son process
exit(0);
}
// forever listenner function
void Client::ndn_forever(){
while(true){
int newsockfd = this->acceptLocal();
string new_prefix = this->get_newprefix();
pid_t fpid1;
while ( ( fpid1 = fork() ) < 0 ){
cout << "create child process failled. Retry..." << endl;
}
if ( 0 == fpid1 ) { // child process
cout<<"child process beginning: "<<endl;
Ndn_socket ndn_socket ;
ndn_socket.listen(new_prefix.data()) ;
ndn_socket.set_daddr(base_server_prefix.data()) ;
cout << "ini daddr :" << ndn_socket.get_daddr() << endl ;
cout << "create ndn_socket in child process" << endl ;
ndn_connSockes5Server(ndn_socket, new_prefix) ;
ndn_transData(ndn_socket, newsockfd) ;
}else{
// close the fds in main process
close(newsockfd);
}
}
}
// server start
void Client::start(){
this->ndn_listen_local(base_listen_prefix.data()) ;
this->ndn_forever() ;
close(this->sockfd) ;
};
// get a new prefix based on the listen prefix
string Client::get_newprefix(){
return (listen_prefix+to_string(p_port_seq++)) ;
// if(listen_prefix.at(listen_prefix.size()-1) != '/'){
// return (listen_prefix+"/"+to_string(p_port_seq++)) ;
// }else{
// return (listen_prefix+to_string(p_port_seq++)) ;
// }
}
// transfer data from local port to socks5-server
void *Client::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=recv(remote_sockfd, data, MAX_SIZE, 0);
cout << "**************recv from browser_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 << ">>>>>>>>>>>>>>>>>>>>thread1 end" << endl ;
delete data;
ndn_socketp->close() ;
cout << ">>>>>>>>>>>>>>>>>>>>ndn_socket closed" << endl ;
close(remote_sockfd) ;
return NULL;
}
// transfer data form socks5-server to local port
void *Client::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 = 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 browser_sockfd len = " << send_len << endl ;
}
}
cout << ">>>>>>>>>>>>>>>>>>>>thread2 end" << endl ;
delete data;
ndn_socketp->close() ;
close(remote_sockfd) ;
return NULL;
}
+92
View File
@@ -0,0 +1,92 @@
#ifndef SOCKS_H_INCLUDED
#define SOCKS_H_INCLUDED
#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>
#include "ccn_p2p/ndn_socket.h"
#define SERV_TCP_PORT 8888 /* Local listening port number */
#define MAX_SIZE 1024*7120
// the address of socks server
#define SOCKS5_SERVER_IP "127.0.0.1"
#define SOCKS5_SERVER_PORT 9011
using namespace std;
using std::pair;
class Client{
private:
// sockfd
int sockfd;
// sockaddr
struct sockaddr_in serv_addr;
/* Local listening port number */
int port;
Ndn_socket mndn_socket ;
// 本地兴趣包监听前缀
string listen_prefix ;
string base_listen_prefix;
// 自增量
unsigned int p_port_seq ;
// 服务器兴趣包监听前缀
string server_prefix ;
string base_server_prefix;
public:
// construction function
Client(const string &s_prefix , const string &m_prefix){
this->port=SERV_TCP_PORT;
this->server_prefix = s_prefix;
this->listen_prefix = m_prefix ;
this->p_port_seq=0;
this->base_listen_prefix=m_prefix+"_base";
this->base_server_prefix=s_prefix+"_base";
mndn_socket.set_daddr(base_server_prefix.data()) ;
cout << "base_server_prefix: "<<base_server_prefix << endl ;
}
Client(int port , const string &s_prefix , const string &m_prefix){
this->port=port;
this->server_prefix = s_prefix ;
this->listen_prefix = m_prefix ;
this->p_port_seq=0;
this->base_listen_prefix=m_prefix+"_base";
this->base_server_prefix=s_prefix+"_base";
mndn_socket.set_daddr(base_server_prefix.data()) ;
cout << "base_server_prefix: "<<base_server_prefix << endl ;
}
~Client(){
}
// listen to the local port
void listenLocal() ;
void ndn_listen_local(string prefix) ;
// waiting for the local port's connection
int acceptLocal();
// connect to the socks5-server
void ndn_connSockes5Server(Ndn_socket &ndn_socket , string new_prefix);
// data transmission shake
void ndn_transData(Ndn_socket &ndn_socket , int newsockfd );
// forever listenner function
void ndn_forever();
// server start
void start();
private :
static void *ndn_thread1(void *val);
static void *ndn_thread2(void *val);
string get_newprefix() ;
};
#endif
Binary file not shown.
+44
View File
@@ -0,0 +1,44 @@
#include "Client.h"
using namespace std;
// 输出提示信息
void alert_usage(){
cout << "Usage : ./client -s /aaa/nfd/vpn/server -c /aaa/nfd/vpn/client" << endl ;
exit(0) ;
}
// 解析参数
void parse_arg(string &server_prefix , string &m_prefix , int argc , char **argv){
if(argc < 5){
alert_usage() ;
}
string cmd1 = argv[1] ;
string cmd2 = argv[3] ;
if(cmd1 == "-s"){
server_prefix = argv[2] ;
}else if(cmd1 == "-c"){
m_prefix = argv[2] ;
}else{
alert_usage() ;
}
if(cmd2 == "-s"){
server_prefix = argv[4] ;
}else if(cmd2 == "-c"){
m_prefix = argv[4] ;
}else{
alert_usage() ;
}
if(server_prefix == "" || m_prefix == "") alert_usage() ;
}
// 主函数入口
int main(int argc , char **argv){
string server_prefix = "/aaa/nfd/vpn/server" ;
string client_prefix = "/aaa/nfd/vpn/client" ;
parse_arg(server_prefix , client_prefix, argc, argv) ;
Client *client=new Client(server_prefix,client_prefix);
client->start();
delete client;
}
Binary file not shown.
Binary file not shown.
+47
View File
@@ -0,0 +1,47 @@
INC_DIR= -I. -I..
SRC_DIR = ./deamon ./face ./common ./table
OBJ_DIR = ./objs
#SRC=$(wildcard $(SRC_DIR)/*.cpp)
SRC= ClientMain.cpp \
Client.cpp \
../ccn_p2p/PriorQueuePool/r_queue.cpp \
../ccn_p2p/PriorQueuePool/PriorQueue.cpp \
../ccn_p2p/PriorQueuePool/QueuePool.cpp \
../ccn_p2p/ndn_socket.cpp
OBJS := $(patsubst %.cpp, %.o,$(SRC))
CC := g++
CFLAGS := -g -std=c++14 ${INC_DIR}
LFLAGS := -lpthread -lpcap -lndn-cxx -lboost_system -ljsoncpp
TARGET := client
all: ${TARGET}
# 下面这个是什么作用?
endndc : ./endndc/endndc.cpp
g++ ./endndc/endndc.cpp -o ./endndc/endndc
$(TARGET): ${OBJS}
$(CC) ${OBJS} -o ${TARGET} $(LFLAGS)
${OBJS} : %.o: %.cpp %.h
${CC} ${CFLAGS} -c $< -o $@
@#echo $^
#$@ 表示目标文件
#$^ 表示所有依赖文件
#$< 表示第一个依赖文件
#$? 表示比目标新的依赖文件列表
clean:
rm -rf $(TARGET) *.o ${OBJS}
test:
echo $(SRC)
echo $(OBJS)
echo $(CFLAGS)
+31
View File
@@ -0,0 +1,31 @@
#include "Socks5Server.h"
using namespace std;
// 输出提示信息
void alert_usage(){
cout << "Usage : ./server -s /aaa/nfd/vpn/server " << endl ;
exit(0) ;
}
// 解析参数
void parse_arg(string &server_prefix , int argc , char **argv){
if(argc < 3){
alert_usage() ;
}
string cmd1 = argv[1] ;
if(cmd1 == "-s"){
server_prefix = argv[2] ;
}else{
alert_usage() ;
}
if(server_prefix == "" ) alert_usage() ;
}
// 主函数入口
int main(int argc , char **argv){
string server_prefix ;
parse_arg(server_prefix , argc , argv) ;
Socks5Server *ss_server=new Socks5Server(server_prefix);
ss_server->start();
delete ss_server;
}
Binary file not shown.
+372
View File
@@ -0,0 +1,372 @@
// 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;
}
+89
View File
@@ -0,0 +1,89 @@
#ifndef SOCKS_H_INCLUDED
#define SOCKS_H_INCLUDED
#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>
#include "ccn_p2p/ndn_socket.h"
#define SERV_TCP_PORT 9011 /* Local listening port number */
#define MAX_SIZE 1024*7120
#define SOCKS5_VERSION 5
using namespace std;
class Socks5Server{
private:
// sockfd
int sockfd;
// sockaddr
struct sockaddr_in serv_addr;
/* Local listening port number */
int port;
// socks version
uint8_t socks_vision;
// 2 commom numbers
uint8_t ui0;
uint8_t ui5;
Ndn_socket mndn_socket ;
string listen_prefix ;
string base_listen_prefix;
unsigned int p_port_seq ;
public:
// construction function
Socks5Server(const string &server_prefix){
this->port=SERV_TCP_PORT;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
this->p_port_seq = 0 ;
this->listen_prefix = server_prefix ;
this->base_listen_prefix=server_prefix+"_base";
}
Socks5Server(int port , const string &server_prefix){
this->port=port;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
this->p_port_seq = 0 ;
this->listen_prefix = server_prefix ;
this->base_listen_prefix=server_prefix+"_base";
}
~Socks5Server(){
}
// listen to the local port
void ndn_listen_local(string prefix) ;
// waiting for the local port's connection
string ndn_accept_local(string new_prefix) ;
// a handshake for the sub-negotiation method
int ndn_negotShake(Ndn_socket &ndn_socket);
// a handshake for the connection information
// to remote server
pair<int,int> ndn_connShake(Ndn_socket &ndn_socket);
// data transmission shake
void ndn_transData(string new_prefix , string client_prefix);
// forever listenner function
void ndn_forever();
// server start
void start();
// ndn 监听线程:数据传输
static void *ndn_thread1(void *val);
static void *ndn_thread2(void *val);
};
#endif
Binary file not shown.
+46
View File
@@ -0,0 +1,46 @@
INC_DIR= -I. -I..
SRC_DIR = ./deamon ./face ./common ./table
OBJ_DIR = ./objs
#SRC=$(wildcard $(SRC_DIR)/*.cpp)
SRC= ServerMain.cpp \
Socks5Server.cpp \
../ccn_p2p/PriorQueuePool/r_queue.cpp \
../ccn_p2p/PriorQueuePool/PriorQueue.cpp \
../ccn_p2p/PriorQueuePool/QueuePool.cpp \
../ccn_p2p/ndn_socket.cpp
OBJS := $(patsubst %.cpp, %.o,$(SRC))
CC := g++
CFLAGS := -g -std=c++14 ${INC_DIR}
LFLAGS := -lpthread -lpcap -lndn-cxx -lboost_system -ljsoncpp
TARGET := server
all: ${TARGET}
endndc : ./endndc/endndc.cpp
g++ ./endndc/endndc.cpp -o ./endndc/endndc
$(TARGET): ${OBJS}
$(CC) ${OBJS} -o ${TARGET} $(LFLAGS)
${OBJS} : %.o: %.cpp %.h
${CC} ${CFLAGS} -c $< -o $@
@#echo $^
#$@ 表示目标文件
#$^ 表示所有依赖文件
#$< 表示第一个依赖文件
#$? 表示比目标新的依赖文件列表
clean:
rm -rf $(TARGET) *.o ${OBJS}
test:
echo $(SRC)
echo $(OBJS)
echo $(CFLAGS)
Binary file not shown.
@@ -0,0 +1,3 @@
{
"CurrentProjectSetting": "无配置"
}
@@ -0,0 +1,7 @@
{
"ExpandedNodes": [
""
],
"SelectedNode": "\\server.cpp",
"PreviewInSolutionExplorer": false
}
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,337 @@
#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>
#include <pthread.h>
#define SERV_TCP_PORT 9011 /* Local listening port number */
#define MAX_SIZE 1024*100
using namespace std;
int sockfd, newsockfd;
// simulate socks5-server
// usage:
// 1. "g++ -o server server.cpp -lpthread"
// 2. "./server"
// curl -v --socks5 127.0.0.1:9011 https://www.baidu.com => ok
// firefox browser => ok
void * thread_fun1(void * val){
int local_sockfd=newsockfd;
int remote_sockfd = *((int*)val);
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(local_sockfd, data, sizeof(data), 0);
cout << "recv from local_sock 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 ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
return NULL;
}
void * thread_fun2(void * val){
int local_sockfd = newsockfd;
int remote_sockfd = *((int*)val);
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(remote_sockfd, data, sizeof(data), 0);
cout << "recv from remote_sock datalen = " << datalen << endl ;
if (datalen <= 0) {
//nothing
break;
}else{
// send to localhost
send_len = send(local_sockfd, data, datalen, 0) ;
cout << "send to local_sockfd len = " << send_len << endl ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
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 = 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
// bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
while( bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
sleep(1) ;
cout << "bind fail" << endl ;
// bind failled.
};
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{
cout<<"not ipv4"<<endl;
close(newsockfd);
continue;
}
//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);
}
}
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);
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 (send(newsockfd, connRrt, 10, 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");
// 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;
}
//////////////////////////////4.Data Exchange (Web Request)-End//////////////////////
}
close(sockfd);
printf("The sockfd is closed.\n");
return 0;
}
@@ -0,0 +1,372 @@
#include "Socks5Server.h"
using namespace std;
// simulate socks5-server
// usage:
// 1. "g++ -c Socks5Server.cpp"
// 2. "g++ -c main.cpp"
// 3. "g++ -o sermax main.o Socks5Server.o -lpthread"
// 4. "./sermax"
// 5. test:
// "curl -v --socks5 127.0.0.1:9011 https://www.baidu.com" => ok
// make firefox browser port 9011 => ok
// local port listenner thread
void* thread_fun1(void* val);
// remote server listenner thread
void* thread_fun2(void* val);
// listen to the local port
void Socks5Server::listenLocal(){
this->sockfd=socket(AF_INET, SOCK_STREAM, 0);
/* bind the local address, so that the cliend can send to server */
bzero((char *)&(this->serv_addr), sizeof(this->serv_addr));
(this->serv_addr).sin_family = AF_INET;
(this->serv_addr).sin_addr.s_addr = htonl(INADDR_ANY);
(this->serv_addr).sin_port = htons(this->port);
// bind
while( bind(this->sockfd, (struct sockaddr *) &(this->serv_addr), sizeof(this->serv_addr)) < 0){
sleep(1) ;
cout << "bind fail" << endl ;
};
listen(this->sockfd,10);
};
// waiting for the local port's connection
int Socks5Server::acceptLocal(){
int newsockfd;
struct sockaddr_in cli_addr;
int cli_len=sizeof(cli_addr);
cout<<"Waitting connection from localhost..."<<endl;
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&cli_len);
if (newsockfd < 0) {
cout<<"can't bind local address"<<endl;
}else{
cout<<"Acceptted a connection from localhost"<<endl;
}
return newsockfd;
};
// a headshake for the sub-negotiation method
int Socks5Server::negotShake(int val){
// right flag, the loop is going on when th flag==0
int flag=0;
// newsockfd
int newsockfd = val;
//Get 2 bytes of information from the client
// - socks version number, total number of negotiation methods
char buf1[1];
char buf2[2];
if (recv(newsockfd, buf2, 2, 0) == -1) {
cout<<"cannot get version-nmethod"<<endl;
}
if ((uint8_t)buf2[0] != this->socks_vision) {
cout<<"socks version is wrong"<<endl;
close(newsockfd);
flag=1;
return flag;
}
if ((uint8_t)buf2[1] <= 0) {
cout<<"nmethod is wrong"<<endl;
close(newsockfd);
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++) {
recv(newsockfd, buf1, 1, 0);
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;
close(newsockfd);
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 (send(newsockfd, msg2, 2, 0) == -1) {
cout<<"cannot send socks-methond-reply"<<endl;
}
return flag;
};
// a headshake for the connection information
// to remote server
pair<int,int> Socks5Server::connShake(int val){
// right flag, the loop is going on when th flag==0
int flag=0;
// newsockfd
int newsockfd = val;
//Get the first four bytes of information
// such as the address type of URL request
// from the client
char buf4[4];
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);
flag=1;
return make_pair(1,1);
}
uint8_t cmd = (uint8_t)buf4[1];
if(cmd!=1){
cout<<"cmd is not 1"<<endl;
close(newsockfd);
flag=1;
return make_pair(1,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;
int remote_addr_length=4;
if (addressType == 1) {//ipv4
r_address=new char[4];
if (recv(newsockfd, r_address, 4, 0) == -1) {
cout<<"cannot get the ipv4\n"<<endl;
}
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;
close(newsockfd);
flag=1;
return make_pair(1,1);
}
//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);
flag=1;
return make_pair(1,1);
}
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;
struct sockaddr_in remote_addr;
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){
memcpy(&(remote_addr.sin_addr.s_addr),domin_address,remote_addr_length);
}
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);
flag=1;
}
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);
}
}
else {
printf("cmd is not connection\n");
close(newsockfd);
flag=1;
}
//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);
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 (send(newsockfd, connRrt, 10, 0) == -1) {
printf("cannot send url-reply\n");
flag=1;
}
}
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");
flag=1;
}
}
return make_pair(remote_sockfd,flag);
};
// data transmission shake
void Socks5Server::transData(pair<int,int> pairval){
int newsockfd = pairval.first;
int remote_sockfd = pairval.second;
printf("Data transmission is beginning.\n");
struct mypara
{
int para1;//参数1
int para2;//参数2
};
struct mypara pstru={newsockfd,remote_sockfd};
// listen to the local port
pthread_t tid1 ;
int ret1 = pthread_create(&tid1,NULL,thread_fun1,&(pstru));
cout<<"thread return1: "<<ret1<<endl;
// listen to the remote server
pthread_t tid2 ;
int ret2 = pthread_create(&tid2,NULL,thread_fun2,&(pstru));
cout<<"thread return2: "<<ret2<<endl;
};
// forever listenner function
void Socks5Server::forever(){
while(true){
int newsockfd = this->acceptLocal();
if(this->negotShake(newsockfd)>0){
cout<<"negotShake error"<<endl;
continue;
}
pair<int,int> pairval=connShake(newsockfd);
if(pairval.second>0){
cout<<"connShake error"<<endl;
continue;
}
int remote_sockfd = pairval.first;
this->transData(make_pair(newsockfd,remote_sockfd));
}
};
// server start
void Socks5Server::start(){
this->listenLocal();
this->forever();
close(this->sockfd);
};
// transfer data form local port to remote server
void * thread_fun1(void* val){
struct mypara
{
int para1;//参数1
int para2;//参数2
};
mypara *pstru;
pstru = (struct mypara *) val;
// pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = pstru->para1;
int remote_sockfd= pstru->para2;
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(local_sockfd, data, sizeof(data), 0);
cout << "recv from local_sock 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 ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
return NULL;
}
// transfer data form remote server to local port
void * thread_fun2(void* val){
struct mypara
{
int para1;//参数1
int para2;//参数2
};
mypara *pstru;
pstru = (struct mypara *) val;
// pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = pstru->para1;
int remote_sockfd= pstru->para2;
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(remote_sockfd, data, sizeof(data), 0);
cout << "recv from remote_sock datalen = " << datalen << endl ;
if (datalen <= 0) {
//nothing
break;
}else{
// send to localhost
send_len = send(local_sockfd, data, datalen, 0) ;
cout << "send to local_sockfd len = " << send_len << endl ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
return NULL;
}
@@ -0,0 +1,68 @@
#ifndef SOCKS_H_INCLUDED
#define SOCKS_H_INCLUDED
#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>
#include <pthread.h>
#define SERV_TCP_PORT 9011 /* Local listening port number */
#define MAX_SIZE 1024*100
#define SOCKS5_VERSION 5
using namespace std;
class Socks5Server{
public:
// sockfd
int sockfd;
// sockaddr
struct sockaddr_in serv_addr;
/* Local listening port number */
int port;
// socks version
uint8_t socks_vision;
// 2 commom numbers
uint8_t ui0;
uint8_t ui5;
public:
// construction function
Socks5Server(){
this->port=SERV_TCP_PORT;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
}
Socks5Server(int port){
this->port=port;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
}
~Socks5Server(){
}
// listen to the local port
void listenLocal();
// waiting for the local port's connection
int acceptLocal();
// a headshake for the sub-negotiation method
int negotShake(int val);
// a headshake for the connection information
// to remote server
pair<int,int> connShake(int val);
// data transmission shake
void transData(pair<int,int> pairval);
// forever listenner function
void forever();
// server start
void start();
};
#endif
Binary file not shown.
+10
View File
@@ -0,0 +1,10 @@
#include "Socks5Server.h"
using namespace std;
int main(){
// new a server
Socks5Server *ss_server=new Socks5Server();
// server start
ss_server->start();
// delete
delete ss_server;
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,456 @@
#include "Socks5Server.h"
using namespace std;
// simulate socks5-server
// usage:
// 1. "g++ -c Socks5Server.cpp"
// 2. "g++ -c main.cpp"
// 3. "g++ -o sermax main.o Socks5Server.o -lpthread"
// 4. "./sermax"
// 5. test:
// "curl -v --socks5 127.0.0.1:9011 https://www.baidu.com" => ok
// make firefox browser port 9011 => ok
// test the ipv6 url:"https://mirrors6.tuna.tsinghua.edu.cn/" => error
// local port listenner thread
void* thread_fun1(void *val);
// remote server listenner thread
void* thread_fun2(void *val);
// listen to the local port
void Socks5Server::listenLocal(){
this->sockfd=socket(AF_INET, SOCK_STREAM, 0);
// do following thing so that we can bind our port again
// int opt = 1;
// int len = sizeof(opt);
// while(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, (socklen_t)len)<0){
// cout<<"set sockopt error"<<endl;
// };
/* bind the local address, so that the cliend can send to server */
bzero((char *)&(this->serv_addr), sizeof(this->serv_addr));
(this->serv_addr).sin_family = AF_INET;
(this->serv_addr).sin_addr.s_addr = htonl(INADDR_ANY);
(this->serv_addr).sin_port = htons(this->port);
// bind
while( bind(this->sockfd, (struct sockaddr *) &(this->serv_addr), sizeof(this->serv_addr)) < 0){
sleep(1) ;
cout << "bind fail" << endl ;
};
listen(this->sockfd,10);
};
// waiting for the local port's connection
int Socks5Server::acceptLocal(){
int newsockfd;
struct sockaddr_in cli_addr;
int cli_len=sizeof(cli_addr);
cout<<"Waitting connection from localhost..."<<endl;
newsockfd = accept(this->sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&cli_len);
// error
while(newsockfd<0){
cout<<"can't accept from local address"<<endl;
close(this->sockfd);
this->listenLocal();
newsockfd = accept(this->sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&cli_len);
}
cout<<"Acceptted a connection from localhost"<<endl;
return newsockfd;
};
// a headshake for the sub-negotiation method
int Socks5Server::negotShake(int val){
// right flag, the loop is going on when th flag==0
int flag=0;
// newsockfd
int newsockfd = val;
//Get 2 bytes of information from the client
// - socks version number, total number of negotiation methods
char buf1[1];
char buf2[2];
if (recv(newsockfd, buf2, 2, 0) == -1) {
cout<<"cannot get version-nmethod"<<endl;
flag=1;
return flag;
}
if ((uint8_t)buf2[0] != this->socks_vision) {
cout<<"socks version is wrong"<<endl;
flag=1;
return flag;
}
if ((uint8_t)buf2[1] <= 0) {
cout<<"nmethod is wrong"<<endl;
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++) {
recv(newsockfd, buf1, 1, 0);
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 (send(newsockfd, msg2, 2, 0) == -1) {
cout<<"cannot send socks-methond-reply"<<endl;
flag=1;
return flag;
}
return flag;
};
// a headshake for the connection information
// to remote server
pair<int,int> Socks5Server::connShake(int val){
// right flag, the loop is going on when th flag==0
int flag=0;
// newsockfd
int newsockfd = val;
//Get the first four bytes of information
// such as the address type of URL request
// from the client
char buf4[4];
if (recv(newsockfd, buf4, 4, 0) == -1) {
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 (recv(newsockfd, r_address, 4, 0) == -1) {
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 if(addressType==4){//ipv6 => error. killed by me in early code
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");
}else{
cout<<"address is not ipv4 or ipv6"<<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) {
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 ipv6"<<endl;
printf("Connected to %s:%d\n",inet_ntoa(remote_addr.sin_addr),remote_addr.sin_port);
}
}else if(addressType == 4){//ipv6 => error
//Connect to remote destination server
struct sockaddr_in6 remote_addr;
remote_sockfd = socket(AF_INET6, SOCK_STREAM, 0);
bzero((char *)&remote_addr, sizeof(remote_addr));
remote_addr.sin6_family = AF_INET6;
memcpy(&(remote_addr.sin6_addr.__in6_u.__u6_addr8),r_address,remote_addr_length);
memcpy(&(remote_addr.sin6_port),r_port,2);
cout<<"connecting to ipv6..."<<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 ipv6"<<endl;
// printf("Connected to %s:%d\n",remote_addr.sin6_addr.__in6_u.__u6_addr8,remote_addr.sin6_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 (send(newsockfd, connRrt, 10, 0) == -1) {
printf("cannot send url-reply\n");
flag=1;
return make_pair(remote_sockfd,flag);
}
}else if(addressType==4){//ipv6 => error
// getsocketname()
sockaddr_in6 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:"<<"(ipv6...)"<<":"<<ntohs(cs_addr.sin6_port)<<endl;
// return info
connRrt=new uint8_t[22];
connRrt[0]=socks_vision;
connRrt[1]=ui0;
connRrt[2]=ui0;
connRrt[3]=addressType;
memcpy(&connRrt[4],&(cs_addr.sin6_addr.__in6_u.__u6_addr8),remote_addr_length);
memcpy(&connRrt[20],&(cs_addr.sin6_port),2);
cout<<"the reply ip:"<<endl;
for(int i=0;i<16;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[20+i]);
}
cout<<endl;
if (send(newsockfd, connRrt, 22, 0) == -1) {
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 (send(newsockfd, err, 6, 0) == -1) {
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::transData(pair<int,int> pairval){
int newsockfd = pairval.first;
int remote_sockfd = pairval.second;
printf("Data transmission is beginning.\n");
int sockfds[2] = {newsockfd,remote_sockfd};
pid_t fpid1;
while ( ( fpid1 = fork() ) < 0 ){
cout << "create child process 1 failture! Next will retry!" << endl;
}
if ( 0 == fpid1 ) {
cout<<"子进程1 beginning: "<<endl;
thread_fun1(sockfds);
cout<<"子进程1 exit()"<<endl;
// close the fd in the son process
close(this->sockfd);
// exit the son process
exit(0);
}
pid_t fpid2;
while ( ( fpid2 = fork() ) < 0 ){
cout << "create child process 2 failture! Next will retry!" << endl;
}
if ( 0 == fpid2 ) {
cout<<"子进程2 beginning: "<<endl;
thread_fun2(sockfds);
cout<<"子进程2 exit()"<<endl;
// close the fd in the son process
close(this->sockfd);
// exit the son process
exit(0);
}
};
// forever listenner function
void Socks5Server::forever(){
while(true){
int newsockfd = this->acceptLocal();
if(this->negotShake(newsockfd)>0){
cout<<"negotShake error"<<endl;
close(newsockfd);
continue;
}
pair<int,int> pairval=connShake(newsockfd);
if(pairval.second>0){
cout<<"connShake error"<<endl;
close(newsockfd);
if(pairval.first>0){
close(pairval.first);
}
continue;
}
int remote_sockfd = pairval.first;
this->transData(make_pair(newsockfd,remote_sockfd));
// close the fds in main process
close(newsockfd);
close(remote_sockfd);
}
};
// server start
void Socks5Server::start(){
this->listenLocal();
this->forever();
close(this->sockfd);
};
// transfer data form local port to remote server
void * thread_fun1(void *val){
//pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = ((int*)val)[0];
int remote_sockfd = ((int*)val)[1];
// cout << local_sockfd << " ==== " << remote_sockfd << endl;
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(local_sockfd, data, sizeof(data), 0);
cout << "recv from local_sock 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 ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
return NULL;
}
// transfer data form remote server to local port
void * thread_fun2(void *val){
//pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = ((int*)val)[0];
int remote_sockfd = ((int*)val)[1];
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(remote_sockfd, data, sizeof(data), 0);
cout << "recv from remote_sock datalen = " << datalen << endl ;
if (datalen <= 0) {
//nothing
break;
}else{
// send to localhost
send_len = send(local_sockfd, data, datalen, 0) ;
cout << "send to local_sockfd len = " << send_len << endl ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
return NULL;
}
@@ -0,0 +1,70 @@
#ifndef SOCKS_H_INCLUDED
#define SOCKS_H_INCLUDED
#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>
// #include <pthread.h>
#define SERV_TCP_PORT 9011 /* Local listening port number */
#define MAX_SIZE 1024*7120
#define SOCKS5_VERSION 5
using namespace std;
class Socks5Server{
public:
// sockfd
int sockfd;
// sockaddr
struct sockaddr_in serv_addr;
/* Local listening port number */
int port;
// socks version
uint8_t socks_vision;
// 2 commom numbers
uint8_t ui0;
uint8_t ui5;
public:
// construction function
Socks5Server(){
this->port=SERV_TCP_PORT;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
}
Socks5Server(int port){
this->port=port;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
}
~Socks5Server(){
}
// listen to the local port
void listenLocal();
// waiting for the local port's connection
int acceptLocal();
// a headshake for the sub-negotiation method
int negotShake(int val);
// a headshake for the connection information
// to remote server
pair<int,int> connShake(int val);
// data transmission shake
void transData(pair<int,int> pairval);
// forever listenner function
void forever();
// server start
void start();
};
#endif
Binary file not shown.
+15
View File
@@ -0,0 +1,15 @@
#include "Socks5Server.h"
// #include "Socks5Server.cpp"
using namespace std;
int main(){
// new a server
Socks5Server *ss_server=new Socks5Server();
// server start
ss_server->start();
// delete
delete ss_server;
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
+186
View File
@@ -0,0 +1,186 @@
// simulate socks5-client. coding by wefree in 2019.08
#include "Client.h"
using namespace std;
// local port listenner thread
void* thread_fun1(void *val);
// remote server listenner thread
void* thread_fun2(void *val);
// listen to the local port
void Client::listenLocal(){
this->sockfd=socket(AF_INET, SOCK_STREAM, 0);
/* bind the local address, so that the cliend can send to server */
bzero((char *)&(this->serv_addr), sizeof(this->serv_addr));
(this->serv_addr).sin_family = AF_INET;
(this->serv_addr).sin_addr.s_addr = htonl(INADDR_ANY);
(this->serv_addr).sin_port = htons(this->port);
// bind
while( bind(this->sockfd, (struct sockaddr *) &(this->serv_addr), sizeof(this->serv_addr)) < 0){
sleep(1) ;
cout << "bind fail" << endl ;
};
listen(this->sockfd,10);
};
// waiting for the local port's connection
int Client::acceptLocal(){
int newsockfd;
struct sockaddr_in cli_addr;
int cli_len=sizeof(cli_addr);
cout<<"Waitting connection [client] ..."<<endl;
newsockfd = accept(this->sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&cli_len);
// error
while(newsockfd<0){
cout<<"can't accept from local address"<<endl;
close(this->sockfd);
this->listenLocal();
newsockfd = accept(this->sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&cli_len);
}
cout<<"Acceptted a connection [client]"<<endl;
return newsockfd;
};
// data transmission shake
void Client::transData(pair<int,int> pairval){
int newsockfd = pairval.first;
int remote_sockfd = pairval.second;
printf("Data transmission is beginning.\n");
int sockfds[2] = {newsockfd,remote_sockfd};
pid_t fpid1;
while ( ( fpid1 = fork() ) < 0 ){
cout << "create child process 1 failled. Retry..." << endl;
}
if ( 0 == fpid1 ) {
cout<<" child process 1 beginning: "<<endl;
thread_fun1(sockfds);
cout<<" child process 1 exit()"<<endl;
// close the fd in the son process
close(this->sockfd);
// exit the son process
exit(0);
}
pid_t fpid2;
while ( ( fpid2 = fork() ) < 0 ){
cout << "create child process 2 failled. Retry..." << endl;
}
if ( 0 == fpid2 ) {
cout<<" child process 2 beginning: "<<endl;
thread_fun2(sockfds);
cout<<" child process 2 exit()"<<endl;
// close the fd in the son process
close(this->sockfd);
// exit the son process
exit(0);
}
};
int Client::connSockes5Server(){
//Connect to remote destination server
struct sockaddr_in remote_addr;
int socks5_sockfd;
socks5_sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero((char *)&remote_addr, sizeof(remote_addr));
remote_addr.sin_family = AF_INET;
remote_addr.sin_addr.s_addr=inet_addr(SOCKS5_SERVER_IP);
remote_addr.sin_port=htons(SOCKS5_SERVER_PORT);
cout<<"connecting to socks5server..."<<endl;
int res_c=connect(socks5_sockfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr));
while(res_c<0){
cout<<"can not connect to the socks server...."<<endl;
sleep(1);
res_c=connect(socks5_sockfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr));
}
cout<<"connected socks5server"<<endl;
printf("Connected to %s:%d\n",inet_ntoa(remote_addr.sin_addr),remote_addr.sin_port);
return socks5_sockfd;
}
// forever listenner function
void Client::forever(){
while(true){
int newsockfd = this->acceptLocal();
int socks5_sockfd=this->connSockes5Server() ;
this->transData(make_pair(newsockfd,socks5_sockfd));
// close the fds in main process
close(newsockfd);
close(socks5_sockfd);
}
};
// server start
void Client::start(){
this->listenLocal();
this->forever();
close(this->sockfd);
};
// transfer data form local port to socks5 server
void * thread_fun1(void *val){
//pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = ((int*)val)[0];
int socks_sockfd = ((int*)val)[1];
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(local_sockfd, data, sizeof(data), 0);
cout << "recv from local_sock datalen = " << datalen << endl ;
if (datalen<= 0) {
// 发送一个特殊数据到代理服务器,提醒其关闭此次连接=>也可以设置心跳包来实现
// 由于这里正常情况下传输的是http格式数据,因此这种特殊数据不会跟不同数据混同
char closedata[10];
string closedata_s="closesocks";
strcpy(closedata,closedata_s.c_str());
send_len = send(socks_sockfd, closedata, 10, 0) ;
cout << "send to socks_sockfd the 'closesocks', len = " << send_len << endl ;
break ;
}else{ // send to socks5 server
send_len = send(socks_sockfd, data, datalen, 0) ;
cout << "send to socks_sockfd len = " << send_len << endl ;
}
}
close(local_sockfd) ;
close(socks_sockfd) ;
return NULL;
}
// transfer data form socks5 server to local port
void * thread_fun2(void *val){
//pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = ((int*)val)[0];
int socks_sockfd = ((int*)val)[1];
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(socks_sockfd, data, sizeof(data), 0);
cout << "recv from socks_sock datalen = " << datalen << endl ;
if (datalen <= 0) {
//nothing to do
break;
}else if(datalen==10){
// cout<<"data[10]: "<<data<<endl;
string data_len10(data,data+10);
if(data_len10=="closesocks"){
break;
}else{
// send to localhost
send_len = send(local_sockfd, data, datalen, 0) ;
cout << "send to local_sockfd len = " << send_len << endl ;
}
}else{
// send to localhost
send_len = send(local_sockfd, data, datalen, 0) ;
cout << "send to local_sockfd len = " << send_len << endl ;
}
}
close(local_sockfd) ;
close(socks_sockfd) ;
return NULL;
}
+57
View File
@@ -0,0 +1,57 @@
#ifndef SOCKS_H_INCLUDED
#define SOCKS_H_INCLUDED
#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 8888 /* Local listening port number */
#define MAX_SIZE 1024*7120
// the address of socks server
#define SOCKS5_SERVER_IP "127.0.0.1"
#define SOCKS5_SERVER_PORT 9011
using namespace std;
class Client{
private:
// sockfd
int sockfd;
// sockaddr
struct sockaddr_in serv_addr;
/* Local listening port number */
int port;
public:
// construction function
Client(){
this->port=SERV_TCP_PORT;
}
Client(int port){
this->port=port;
}
~Client(){
}
// listen to the local port
void listenLocal();
// waiting for the local port's connection
int acceptLocal();
// connect to the socks server
int connSockes5Server();
// data transmission shake
void transData(pair<int,int> pairval);
// forever listenner function
void forever();
// server start
void start();
};
#endif
Binary file not shown.
@@ -0,0 +1,26 @@
#include "Client.h"
using namespace std;
// simulate socks5-client
// usage:
// 1. "g++ -c Client.cpp"
// 2. "g++ -c ClientMain.cpp"
// 3. "g++ -o client ClientMain.o Client.o"
// 4. "./client"
// 5. test:
// "curl -v --socks5 127.0.0.1:8888 https://www.baidu.com" => ok
// make firefox browser port 8888 => ok
int main(){
Client *client=new Client();
client->start();
delete client;
}
// makefile:
// client: Client.o ClientMain.o
// g++ -o client ClientMain.o Client.o
// Client.o : Client.cpp Client.h
// g++ -c Client.cpp
// ClientMain.o : ClientMain.cpp
// g++ -c ClientMain.cpp
Binary file not shown.
@@ -0,0 +1,27 @@
#include "Socks5Server.h"
using namespace std;
// simulate socks5-server
// usage:
// 1. "g++ -c Socks5Server.cpp"
// 2. "g++ -c ServerMain.cpp"
// 3. "g++ -o server ServerMain.o Socks5Server.o"
// 4. "./server"
// 5. test:
// "curl -v --socks5 127.0.0.1:9011 https://www.baidu.com" => ok
// make firefox browser port 9011 => ok
int main(){
Socks5Server *ss_server=new Socks5Server();
ss_server->start();
delete ss_server;
}
// makefile:
// server : Socks5Server.o ServerMain.o
// g++ -o server ServerMain.o Socks5Server.o
// Socks5Server.o : Socks5Server.cpp Socks5Server.h
// g++ -c Socks5Server.cpp
// ServerMain.o : ServerMain.cpp
// g++ -c ServerMain.cpp
Binary file not shown.
@@ -0,0 +1,400 @@
// simulate socks5-server. coding by wefree in 2019.08
#include "Socks5Server.h"
using namespace std;
// local port listenner thread
void* thread_fun1(void *val);
// remote server listenner thread
void* thread_fun2(void *val);
// listen to the local port
void Socks5Server::listenLocal(){
this->sockfd=socket(AF_INET, SOCK_STREAM, 0);
/* bind the local address, so that the cliend can send to server */
bzero((char *)&(this->serv_addr), sizeof(this->serv_addr));
(this->serv_addr).sin_family = AF_INET;
(this->serv_addr).sin_addr.s_addr = htonl(INADDR_ANY);
(this->serv_addr).sin_port = htons(this->port);
// bind
while( bind(this->sockfd, (struct sockaddr *) &(this->serv_addr), sizeof(this->serv_addr)) < 0){
sleep(1) ;
cout << "bind fail" << endl ;
};
listen(this->sockfd,10);
};
// waiting for the local port's connection
int Socks5Server::acceptLocal(){
int newsockfd;
struct sockaddr_in cli_addr;
int cli_len=sizeof(cli_addr);
cout<<"Waitting connection [socks5 server] ..."<<endl;
newsockfd = accept(this->sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&cli_len);
// error
while(newsockfd<0){
cout<<"can't accept from local address"<<endl;
close(this->sockfd);
this->listenLocal();
newsockfd = accept(this->sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&cli_len);
}
cout<<"Acceptted a connection [socks5 server]"<<endl;
return newsockfd;
};
// a headshake for the sub-negotiation method
int Socks5Server::negotShake(int val){
// right flag, the loop is going on when th flag==0
int flag=0;
// newsockfd
int newsockfd = val;
//Get 2 bytes of information from the client
// - socks version number, total number of negotiation methods
char buf1[1];
char buf2[2];
if (recv(newsockfd, buf2, 2, 0) == -1) {
cout<<"cannot get version-nmethod"<<endl;
flag=1;
return flag;
}
if ((uint8_t)buf2[0] != this->socks_vision) {
cout<<"socks version is wrong"<<endl;
flag=1;
return flag;
}
if ((uint8_t)buf2[1] <= 0) {
cout<<"nmethod is wrong"<<endl;
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++) {
recv(newsockfd, buf1, 1, 0);
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 (send(newsockfd, msg2, 2, 0) == -1) {
cout<<"cannot send socks-methond-reply"<<endl;
flag=1;
return flag;
}
return flag;
};
// a headshake for the connection information
// to remote server
pair<int,int> Socks5Server::connShake(int val){
// right flag, the loop is going on when th flag==0
int flag=0;
// newsockfd
int newsockfd = val;
//Get the first four bytes of information
// such as the address type of URL request
// from the client
char buf4[4];
if (recv(newsockfd, buf4, 4, 0) == -1) {
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 (recv(newsockfd, r_address, 4, 0) == -1) {
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) {
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 ipv6"<<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 (send(newsockfd, connRrt, 10, 0) == -1) {
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 (send(newsockfd, err, 6, 0) == -1) {
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::transData(pair<int,int> pairval){
int newsockfd = pairval.first;
int remote_sockfd = pairval.second;
printf("Data transmission is beginning.\n");
int sockfds[2] = {newsockfd,remote_sockfd};
pid_t fpid1;
while ( ( fpid1 = fork() ) < 0 ){
cout << "create child process 1 failled. Retry..." << endl;
}
if ( 0 == fpid1 ) {
cout<<"child process 1 beginning: "<<endl;
thread_fun1(sockfds);
cout<<"child process 1 exit()"<<endl;
// close the fd in the son process
close(this->sockfd);
// exit the son process
exit(0);
}
pid_t fpid2;
while ( ( fpid2 = fork() ) < 0 ){
cout << "create child process 2 failled. Retry..." << endl;
}
if ( 0 == fpid2 ) {
cout<<"child process 2 beginning: "<<endl;
thread_fun2(sockfds);
cout<<"child process 2 exit()"<<endl;
// close the fd in the son process
close(this->sockfd);
// exit the son process
exit(0);
}
};
// forever listenner function
void Socks5Server::forever(){
while(true){
int newsockfd = this->acceptLocal();
if(this->negotShake(newsockfd)>0){
cout<<"negotShake error"<<endl;
close(newsockfd);
continue;
}
pair<int,int> pairval=connShake(newsockfd);
if(pairval.second>0){
cout<<"connShake error"<<endl;
close(newsockfd);
if(pairval.first>0){
close(pairval.first);
}
continue;
}
int remote_sockfd = pairval.first;
this->transData(make_pair(newsockfd,remote_sockfd));
// close the fds in main process
close(newsockfd);
close(remote_sockfd);
}
};
// server start
void Socks5Server::start(){
this->listenLocal();
this->forever();
close(this->sockfd);
};
// transfer data form local port to remote server
void * thread_fun1(void *val){
//pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = ((int*)val)[0];
int remote_sockfd = ((int*)val)[1];
// cout << local_sockfd << " ==== " << remote_sockfd << endl;
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(local_sockfd, data, sizeof(data), 0);
cout << "recv from local_sock datalen = " << datalen << endl ;
if (datalen<= 0) {
// nothing to do
break ;
}else if(datalen==10){
// cout<<"data[10]: "<<data<<endl;
string data_len10(data,data+10);
if(data_len10=="closesocks"){
break;
}else{
send_len = send(remote_sockfd, data, datalen, 0) ;
cout << "send to remote_sockfd len = " << send_len << endl ;
}
}else{ // send to remote server
send_len = send(remote_sockfd, data, datalen, 0) ;
cout << "send to remote_sockfd len = " << send_len << endl ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
return NULL;
}
// transfer data form remote server to local port
void * thread_fun2(void *val){
//pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = ((int*)val)[0];
int remote_sockfd = ((int*)val)[1];
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(remote_sockfd, data, sizeof(data), 0);
cout << "recv from remote_sock datalen = " << datalen << endl ;
if (datalen <= 0) {
// 发送一个特殊数据到客户端,提醒其关闭此次连接=>也可以设置心跳包来实现
// 由于这里正常情况下传输的是http格式数据,因此这种特殊数据不会跟不同数据混同
char closedata[10];
string closedata_s="closesocks";
strcpy(closedata,closedata_s.c_str());
send_len = send(local_sockfd, closedata, 10, 0) ;
cout << "send to client_sockfd the 'closesocks', len = " << send_len << endl ;
break;
}else{
// send to localhost
send_len = send(local_sockfd, data, datalen, 0) ;
cout << "send to local_sockfd len = " << send_len << endl ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
return NULL;
}
@@ -0,0 +1,69 @@
#ifndef SOCKS_H_INCLUDED
#define SOCKS_H_INCLUDED
#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 1024*7120
#define SOCKS5_VERSION 5
using namespace std;
class Socks5Server{
private:
// sockfd
int sockfd;
// sockaddr
struct sockaddr_in serv_addr;
/* Local listening port number */
int port;
// socks version
uint8_t socks_vision;
// 2 commom numbers
uint8_t ui0;
uint8_t ui5;
public:
// construction function
Socks5Server(){
this->port=SERV_TCP_PORT;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
}
Socks5Server(int port){
this->port=port;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
}
~Socks5Server(){
}
// listen to the local port
void listenLocal();
// waiting for the local port's connection
int acceptLocal();
// a headshake for the sub-negotiation method
int negotShake(int val);
// a headshake for the connection information
// to remote server
pair<int,int> connShake(int val);
// data transmission shake
void transData(pair<int,int> pairval);
// forever listenner function
void forever();
// server start
void start();
};
#endif
Binary file not shown.
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
client: Client.o ClientMain.o
g++ -o client ClientMain.o Client.o
Client.o : Client.cpp Client.h
g++ -c Client.cpp
ClientMain.o : ClientMain.cpp
g++ -c ClientMain.cpp
Binary file not shown.
+61
View File
@@ -0,0 +1,61 @@
import logging
import select
import socket
import struct
from socketserver import ThreadingMixIn, TCPServer, StreamRequestHandler
logging.basicConfig(level=logging.DEBUG)
# SOCKS_VERSION = 5
socks_address='127.0.0.1'
socks_port=9011
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
pass
class SocksClient(StreamRequestHandler):
def handle(self):
logging.info('Accepting connection from %s:%s' % self.client_address)
# 建立与socks服务器的连接
try:
socks_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socks_server.connect((socks_address, socks_port))
logging.info('Connected to %s %s' % (socks_address,socks_port))
except Exception as err:
logging.error(err)
# 建立一个本机与代理服务器之间的数据交换连接
self.exchange_loop(self.connection, socks_server)
# 关闭本机数据连接(但继续监听)
self.server.close_request(self.request)
# 作为客户端,交换本机与代理服务器的数据
def exchange_loop(self, client, socks_server):
count = 0
while True:
count = count + 1
r, w, e = select.select([client, socks_server], [], [])
# 如果client监听到了来自本机的数据,读取这个数据;
# 并让socks_server发送给本机。
if client in r:
data = client.recv(4096)
print("client recv: "+count)
if socks_server.send(data) <= 0:
break
# 如果socks_server监听到了来自代理服务器的数据,读取这个数据;
# 并让client发送给本机。
if socks_server in r:
data = socks_server.recv(4096)
print("server recv: " + count)
if client.send(data) <= 0:
break
if __name__ == '__main__':
# 创建一个本机数据监听,端口号为8000
with ThreadingTCPServer(('127.0.0.1', 8000), SocksClient) as client:
client.serve_forever()
Binary file not shown.
+118
View File
@@ -0,0 +1,118 @@
import logging
import select
import socket
import struct
from socketserver import ThreadingMixIn, TCPServer, StreamRequestHandler
logging.basicConfig(level=logging.DEBUG)
SOCKS_VERSION = 5
socks_address='127.0.0.1'
socks_port=9011
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
pass
class SocksProxy(StreamRequestHandler):
def handle(self):
logging.info('Accepting connection from %s:%s' % self.client_address)
# 从客户端获取两个字节的连接代理服务器请求
header = self.connection.recv(2) #11111111111111111111111-2
# !表示network
version, nmethods = struct.unpack("!BB", header)
# socks 5
assert version == SOCKS_VERSION
assert nmethods > 0
# 获取客户端提供的子协商方法
methods = self.get_available_methods(nmethods)
# 如果子协商方法中不存在不需要子协商验证,就关闭此次连接
if 0 not in set(methods):
self.server.close_request(self.request)
return
# 返回选择的验证方式及socks版本
self.connection.sendall(struct.pack("!BB", SOCKS_VERSION, 0))
# 客户端获得url请求的前几个字节
version, cmd, _, address_type = struct.unpack("!BBBB", self.connection.recv(4))
assert version == SOCKS_VERSION
if address_type == 1: # IPv4
address = socket.inet_ntoa(self.connection.recv(4))
elif address_type == 3: # Domain name
domain_length = ord(self.connection.recv(1)[0])
address = self.connection.recv(domain_length)
port = struct.unpack('!H', self.connection.recv(2))[0]
# 代理服务器对url请求在尝试进行连接之后,向客户端进行连接状态的答复
try:
if cmd == 1: # CONNECT
remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote.connect((address, port))
bind_address = remote.getsockname()
logging.info('Connected to %s %s' % (address, port))
else:
self.server.close_request(self.request)
addr = struct.unpack("!I", socket.inet_aton(bind_address[0]))[0]
port = bind_address[1]
reply = struct.pack("!BBBBIH", SOCKS_VERSION, 0, 0, address_type,
addr, port)
except Exception as err:
logging.error(err)
reply = self.generate_failed_reply(address_type, 5)
self.connection.sendall(reply)
# 建立一个数据交换连接
if reply[1] == 0 and cmd == 1:
self.exchange_loop(self.connection, remote)
# 数据交换结束,关闭此次代理请求
self.server.close_request(self.request)
def get_available_methods(self, n):
methods = []
for i in range(n):
methods.append(ord(self.connection.recv(1)))
return methods
# 代理服务器对发生错误的url请求进行
def generate_failed_reply(self, address_type, error_number):
return struct.pack("!BBBBIH", SOCKS_VERSION, error_number, 0, address_type, 0, 0)
# 作为代理服务器,交换客户端与远程目的服务器的数据
def exchange_loop(self, client, remote):
count = 0
while True:
count = count + 1
r, w, e = select.select([client, remote], [], [])
# 如果client监听到了来自客户端的数据,读取这个数据;
# 并让remoto发送这个数据到远程目的服务器。
if client in r:
data = client.recv(4096)
print("client recv: " )
if remote.send(data) <= 0:
break
# 如果remote监听到了来自远程目的服务器的数据,读取这个数据;
# 并让client发送给客户端。
if remote in r:
data = remote.recv(4096)
print("server recv: " )
if client.send(data) <= 0:
break
if __name__ == '__main__':
# 创建一个代理服务器监听
with ThreadingTCPServer(('127.0.0.1', 9011), SocksProxy) as server:
server.serve_forever()
# curl -v --socks5 127.0.0.1:9011 https://github.com
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,444 @@
#include "Socks5Server.h"
using namespace std;
// simulate socks5-server
// usage:
// 1. "g++ -c Socks5Server.cpp"
// 2. "g++ -c main.cpp"
// 3. "g++ -o sermax main.o Socks5Server.o -lpthread"
// 4. "./sermax"
// 5. test:
// "curl -v --socks5 127.0.0.1:9011 https://www.baidu.com" => ok
// make firefox browser port 9011 => ok
// test the ipv6 url:"https://mirrors6.tuna.tsinghua.edu.cn/" => error
// 6. Mind: Do not open too many urls, it may make the ipv6 url to kill the program!!!
// local port listenner thread
void* thread_fun1(void *val);
// remote server listenner thread
void* thread_fun2(void *val);
// listen to the local port
void Socks5Server::listenLocal(){
this->sockfd=socket(AF_INET, SOCK_STREAM, 0);
/* bind the local address, so that the cliend can send to server */
bzero((char *)&(this->serv_addr), sizeof(this->serv_addr));
(this->serv_addr).sin_family = AF_INET;
(this->serv_addr).sin_addr.s_addr = htonl(INADDR_ANY);
(this->serv_addr).sin_port = htons(this->port);
// bind
while( bind(this->sockfd, (struct sockaddr *) &(this->serv_addr), sizeof(this->serv_addr)) < 0){
sleep(1) ;
cout << "bind fail" << endl ;
};
listen(this->sockfd,10);
};
// waiting for the local port's connection
int Socks5Server::acceptLocal(){
int newsockfd;
struct sockaddr_in cli_addr;
int cli_len=sizeof(cli_addr);
cout<<"Waitting connection from localhost..."<<endl;
newsockfd = accept(this->sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&cli_len);
// error
while(newsockfd<0){
cout<<"can't accept from local address"<<endl;
close(this->sockfd);
this->listenLocal();
newsockfd = accept(this->sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&cli_len);
}
cout<<"Acceptted a connection from localhost"<<endl;
return newsockfd;
};
// a headshake for the sub-negotiation method
int Socks5Server::negotShake(int val){
// right flag, the loop is going on when th flag==0
int flag=0;
// newsockfd
int newsockfd = val;
//Get 2 bytes of information from the client
// - socks version number, total number of negotiation methods
char buf1[1];
char buf2[2];
if (recv(newsockfd, buf2, 2, 0) == -1) {
cout<<"cannot get version-nmethod"<<endl;
flag=1;
return flag;
}
if ((uint8_t)buf2[0] != this->socks_vision) {
cout<<"socks version is wrong"<<endl;
flag=1;
return flag;
}
if ((uint8_t)buf2[1] <= 0) {
cout<<"nmethod is wrong"<<endl;
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++) {
recv(newsockfd, buf1, 1, 0);
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 (send(newsockfd, msg2, 2, 0) == -1) {
cout<<"cannot send socks-methond-reply"<<endl;
flag=1;
return flag;
}
return flag;
};
// a headshake for the connection information
// to remote server
pair<int,int> Socks5Server::connShake(int val){
// right flag, the loop is going on when th flag==0
int flag=0;
// newsockfd
int newsockfd = val;
//Get the first four bytes of information
// such as the address type of URL request
// from the client
char buf4[4];
if (recv(newsockfd, buf4, 4, 0) == -1) {
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 (recv(newsockfd, r_address, 4, 0) == -1) {
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 if(addressType==4){//ipv6 => error. killed by me in early code
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");
}else{
cout<<"address is not ipv4 or ipv6"<<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) {
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 ipv6"<<endl;
printf("Connected to %s:%d\n",inet_ntoa(remote_addr.sin_addr),remote_addr.sin_port);
}
}else if(addressType == 4){//ipv6 => error
//Connect to remote destination server
struct sockaddr_in6 remote_addr;
remote_sockfd = socket(AF_INET6, SOCK_STREAM, 0);
bzero((char *)&remote_addr, sizeof(remote_addr));
remote_addr.sin6_family = AF_INET6;
memcpy(&(remote_addr.sin6_addr.__in6_u.__u6_addr8),r_address,remote_addr_length);
memcpy(&(remote_addr.sin6_port),r_port,2);
cout<<"connecting to ipv6..."<<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 ipv6"<<endl;
// printf("Connected to %s:%d\n",remote_addr.sin6_addr.__in6_u.__u6_addr8,remote_addr.sin6_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 (send(newsockfd, connRrt, 10, 0) == -1) {
printf("cannot send url-reply\n");
flag=1;
return make_pair(remote_sockfd,flag);
}
}else if(addressType==4){//ipv6 => error
// getsocketname()
sockaddr_in6 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:"<<"(ipv6...)"<<":"<<ntohs(cs_addr.sin6_port)<<endl;
// return info
connRrt=new uint8_t[22];
connRrt[0]=socks_vision;
connRrt[1]=ui0;
connRrt[2]=ui0;
connRrt[3]=addressType;
memcpy(&connRrt[4],&(cs_addr.sin6_addr.__in6_u.__u6_addr8),remote_addr_length);
memcpy(&connRrt[20],&(cs_addr.sin6_port),2);
cout<<"the reply ip:"<<endl;
for(int i=0;i<16;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[20+i]);
}
cout<<endl;
if (send(newsockfd, connRrt, 22, 0) == -1) {
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 (send(newsockfd, err, 6, 0) == -1) {
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::transData(pair<int,int> pairval){
int newsockfd = pairval.first;
int remote_sockfd = pairval.second;
printf("Data transmission is beginning.\n");
// listen to the local port
pthread_t tid1 ;
int sockfds[2] = {newsockfd,remote_sockfd};
int fpid1;
while ( ( fpid1 = fork() ) < 0 ){
cout << "create child process 1 failture! Next will retry!" << endl;
}
if ( 0 == fpid1 ) {
cout<<"子进程1 beginning: "<<endl;
thread_fun1(sockfds);
cout<<"子进程1 exit()"<<endl;
exit(0);
}
int fpid2;
while ( ( fpid2 = fork() ) < 0 ){
cout << "create child process 2 failture! Next will retry!" << endl;
}
if ( 0 == fpid2 ) {
cout<<"子进程2 beginning: "<<endl;
thread_fun2(sockfds);
cout<<"子进程2 exit()"<<endl;
exit(0);
}
};
// forever listenner function
void Socks5Server::forever(){
while(true){
int newsockfd = this->acceptLocal();
if(this->negotShake(newsockfd)>0){
cout<<"negotShake error"<<endl;
close(newsockfd);
continue;
}
pair<int,int> pairval=connShake(newsockfd);
if(pairval.second>0){
cout<<"connShake error"<<endl;
close(newsockfd);
if(pairval.first>0){
close(pairval.first);
}
continue;
}
int remote_sockfd = pairval.first;
this->transData(make_pair(newsockfd,remote_sockfd));
}
};
// server start
void Socks5Server::start(){
this->listenLocal();
this->forever();
close(this->sockfd);
};
// transfer data form local port to remote server
void * thread_fun1(void *val){
//pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = ((int*)val)[0];
int remote_sockfd = ((int*)val)[1];
// cout << local_sockfd << " ==== " << remote_sockfd << endl;
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(local_sockfd, data, sizeof(data), 0);
cout << "recv from local_sock 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 ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
return NULL;
}
// transfer data form remote server to local port
void * thread_fun2(void *val){
//pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = ((int*)val)[0];
int remote_sockfd = ((int*)val)[1];
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(remote_sockfd, data, sizeof(data), 0);
cout << "recv from remote_sock datalen = " << datalen << endl ;
if (datalen <= 0) {
//nothing
break;
}else{
// send to localhost
send_len = send(local_sockfd, data, datalen, 0) ;
cout << "send to local_sockfd len = " << send_len << endl ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
return NULL;
}
@@ -0,0 +1,70 @@
#ifndef SOCKS_H_INCLUDED
#define SOCKS_H_INCLUDED
#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>
// #include <pthread.h>
#define SERV_TCP_PORT 9011 /* Local listening port number */
#define MAX_SIZE 1024*7120
#define SOCKS5_VERSION 5
using namespace std;
class Socks5Server{
public:
// sockfd
int sockfd;
// sockaddr
struct sockaddr_in serv_addr;
/* Local listening port number */
int port;
// socks version
uint8_t socks_vision;
// 2 commom numbers
uint8_t ui0;
uint8_t ui5;
public:
// construction function
Socks5Server(){
this->port=SERV_TCP_PORT;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
}
Socks5Server(int port){
this->port=port;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
}
~Socks5Server(){
}
// listen to the local port
void listenLocal();
// waiting for the local port's connection
int acceptLocal();
// a headshake for the sub-negotiation method
int negotShake(int val);
// a headshake for the connection information
// to remote server
pair<int,int> connShake(int val);
// data transmission shake
void transData(pair<int,int> pairval);
// forever listenner function
void forever();
// server start
void start();
};
#endif
@@ -0,0 +1,15 @@
#include "Socks5Server.h"
// #include "Socks5Server.cpp"
using namespace std;
int main(){
// new a server
Socks5Server *ss_server=new Socks5Server();
// server start
ss_server->start();
// delete
delete ss_server;
}
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,457 @@
#include "Socks5Server.h"
using namespace std;
// simulate socks5-server
// usage:
// 1. "g++ -c Socks5Server.cpp"
// 2. "g++ -c main.cpp"
// 3. "g++ -o sermax main.o Socks5Server.o -lpthread"
// 4. "./sermax"
// 5. test:
// "curl -v --socks5 127.0.0.1:9011 https://www.baidu.com" => ok
// make firefox browser port 9011 => ok
// test the ipv6 url:"https://mirrors6.tuna.tsinghua.edu.cn/" => error
// 6. Mind: Do not open too many urls, it may make the ipv6 url to kill the program!!!
// local port listenner thread
void* thread_fun1(void *val);
// remote server listenner thread
void* thread_fun2(void *val);
// listen to the local port
void Socks5Server::listenLocal(){
this->sockfd=socket(AF_INET, SOCK_STREAM, 0);
// do following thing so that we can bind our port again
// int opt = 1;
// int len = sizeof(opt);
// while(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, (socklen_t)len)<0){
// cout<<"set sockopt error"<<endl;
// };
/* bind the local address, so that the cliend can send to server */
bzero((char *)&(this->serv_addr), sizeof(this->serv_addr));
(this->serv_addr).sin_family = AF_INET;
(this->serv_addr).sin_addr.s_addr = htonl(INADDR_ANY);
(this->serv_addr).sin_port = htons(this->port);
// bind
while( bind(this->sockfd, (struct sockaddr *) &(this->serv_addr), sizeof(this->serv_addr)) < 0){
sleep(1) ;
cout << "bind fail" << endl ;
};
listen(this->sockfd,10);
};
// waiting for the local port's connection
int Socks5Server::acceptLocal(){
int newsockfd;
struct sockaddr_in cli_addr;
int cli_len=sizeof(cli_addr);
cout<<"Waitting connection from localhost..."<<endl;
newsockfd = accept(this->sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&cli_len);
// error
while(newsockfd<0){
cout<<"can't accept from local address"<<endl;
close(this->sockfd);
this->listenLocal();
newsockfd = accept(this->sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&cli_len);
}
cout<<"Acceptted a connection from localhost"<<endl;
return newsockfd;
};
// a headshake for the sub-negotiation method
int Socks5Server::negotShake(int val){
// right flag, the loop is going on when th flag==0
int flag=0;
// newsockfd
int newsockfd = val;
//Get 2 bytes of information from the client
// - socks version number, total number of negotiation methods
char buf1[1];
char buf2[2];
if (recv(newsockfd, buf2, 2, 0) == -1) {
cout<<"cannot get version-nmethod"<<endl;
flag=1;
return flag;
}
if ((uint8_t)buf2[0] != this->socks_vision) {
cout<<"socks version is wrong"<<endl;
flag=1;
return flag;
}
if ((uint8_t)buf2[1] <= 0) {
cout<<"nmethod is wrong"<<endl;
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++) {
recv(newsockfd, buf1, 1, 0);
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 (send(newsockfd, msg2, 2, 0) == -1) {
cout<<"cannot send socks-methond-reply"<<endl;
flag=1;
return flag;
}
return flag;
};
// a headshake for the connection information
// to remote server
pair<int,int> Socks5Server::connShake(int val){
// right flag, the loop is going on when th flag==0
int flag=0;
// newsockfd
int newsockfd = val;
//Get the first four bytes of information
// such as the address type of URL request
// from the client
char buf4[4];
if (recv(newsockfd, buf4, 4, 0) == -1) {
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 (recv(newsockfd, r_address, 4, 0) == -1) {
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 if(addressType==4){//ipv6 => error. killed by me in early code
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");
}else{
cout<<"address is not ipv4 or ipv6"<<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) {
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 ipv6"<<endl;
printf("Connected to %s:%d\n",inet_ntoa(remote_addr.sin_addr),remote_addr.sin_port);
}
}else if(addressType == 4){//ipv6 => error
//Connect to remote destination server
struct sockaddr_in6 remote_addr;
remote_sockfd = socket(AF_INET6, SOCK_STREAM, 0);
bzero((char *)&remote_addr, sizeof(remote_addr));
remote_addr.sin6_family = AF_INET6;
memcpy(&(remote_addr.sin6_addr.__in6_u.__u6_addr8),r_address,remote_addr_length);
memcpy(&(remote_addr.sin6_port),r_port,2);
cout<<"connecting to ipv6..."<<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 ipv6"<<endl;
// printf("Connected to %s:%d\n",remote_addr.sin6_addr.__in6_u.__u6_addr8,remote_addr.sin6_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 (send(newsockfd, connRrt, 10, 0) == -1) {
printf("cannot send url-reply\n");
flag=1;
return make_pair(remote_sockfd,flag);
}
}else if(addressType==4){//ipv6 => error
// getsocketname()
sockaddr_in6 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:"<<"(ipv6...)"<<":"<<ntohs(cs_addr.sin6_port)<<endl;
// return info
connRrt=new uint8_t[22];
connRrt[0]=socks_vision;
connRrt[1]=ui0;
connRrt[2]=ui0;
connRrt[3]=addressType;
memcpy(&connRrt[4],&(cs_addr.sin6_addr.__in6_u.__u6_addr8),remote_addr_length);
memcpy(&connRrt[20],&(cs_addr.sin6_port),2);
cout<<"the reply ip:"<<endl;
for(int i=0;i<16;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[20+i]);
}
cout<<endl;
if (send(newsockfd, connRrt, 22, 0) == -1) {
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 (send(newsockfd, err, 6, 0) == -1) {
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::transData(pair<int,int> pairval){
int newsockfd = pairval.first;
int remote_sockfd = pairval.second;
printf("Data transmission is beginning.\n");
int sockfds[2] = {newsockfd,remote_sockfd};
pid_t fpid1;
while ( ( fpid1 = fork() ) < 0 ){
cout << "create child process 1 failture! Next will retry!" << endl;
}
if ( 0 == fpid1 ) {
cout<<"子进程1 beginning: "<<endl;
thread_fun1(sockfds);
cout<<"子进程1 exit()"<<endl;
// close the fd in the son process
close(this->sockfd);
// exit the son process
exit(0);
}
pid_t fpid2;
while ( ( fpid2 = fork() ) < 0 ){
cout << "create child process 2 failture! Next will retry!" << endl;
}
if ( 0 == fpid2 ) {
cout<<"子进程2 beginning: "<<endl;
thread_fun2(sockfds);
cout<<"子进程2 exit()"<<endl;
// close the fd in the son process
close(this->sockfd);
// exit the son process
exit(0);
}
};
// forever listenner function
void Socks5Server::forever(){
while(true){
int newsockfd = this->acceptLocal();
if(this->negotShake(newsockfd)>0){
cout<<"negotShake error"<<endl;
close(newsockfd);
continue;
}
pair<int,int> pairval=connShake(newsockfd);
if(pairval.second>0){
cout<<"connShake error"<<endl;
close(newsockfd);
if(pairval.first>0){
close(pairval.first);
}
continue;
}
int remote_sockfd = pairval.first;
this->transData(make_pair(newsockfd,remote_sockfd));
// close the fds in main process
close(newsockfd);
close(remote_sockfd);
}
};
// server start
void Socks5Server::start(){
this->listenLocal();
this->forever();
close(this->sockfd);
};
// transfer data form local port to remote server
void * thread_fun1(void *val){
//pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = ((int*)val)[0];
int remote_sockfd = ((int*)val)[1];
// cout << local_sockfd << " ==== " << remote_sockfd << endl;
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(local_sockfd, data, sizeof(data), 0);
cout << "recv from local_sock 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 ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
return NULL;
}
// transfer data form remote server to local port
void * thread_fun2(void *val){
//pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = ((int*)val)[0];
int remote_sockfd = ((int*)val)[1];
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(remote_sockfd, data, sizeof(data), 0);
cout << "recv from remote_sock datalen = " << datalen << endl ;
if (datalen <= 0) {
//nothing
break;
}else{
// send to localhost
send_len = send(local_sockfd, data, datalen, 0) ;
cout << "send to local_sockfd len = " << send_len << endl ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
return NULL;
}
@@ -0,0 +1,70 @@
#ifndef SOCKS_H_INCLUDED
#define SOCKS_H_INCLUDED
#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>
// #include <pthread.h>
#define SERV_TCP_PORT 9011 /* Local listening port number */
#define MAX_SIZE 1024*7120
#define SOCKS5_VERSION 5
using namespace std;
class Socks5Server{
public:
// sockfd
int sockfd;
// sockaddr
struct sockaddr_in serv_addr;
/* Local listening port number */
int port;
// socks version
uint8_t socks_vision;
// 2 commom numbers
uint8_t ui0;
uint8_t ui5;
public:
// construction function
Socks5Server(){
this->port=SERV_TCP_PORT;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
}
Socks5Server(int port){
this->port=port;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
}
~Socks5Server(){
}
// listen to the local port
void listenLocal();
// waiting for the local port's connection
int acceptLocal();
// a headshake for the sub-negotiation method
int negotShake(int val);
// a headshake for the connection information
// to remote server
pair<int,int> connShake(int val);
// data transmission shake
void transData(pair<int,int> pairval);
// forever listenner function
void forever();
// server start
void start();
};
#endif
@@ -0,0 +1,15 @@
#include "Socks5Server.h"
// #include "Socks5Server.cpp"
using namespace std;
int main(){
// new a server
Socks5Server *ss_server=new Socks5Server();
// server start
ss_server->start();
// delete
delete ss_server;
}
Binary file not shown.
+374
View File
@@ -0,0 +1,374 @@
#include "Socks5Server.h"
using namespace std;
// simulate socks5-server
// usage:
// 1. "g++ -c Socks5Server.cpp"
// 2. "g++ -c main.cpp"
// 3. "g++ -o sermax main.o Socks5Server.o -lpthread"
// 4. "./sermax"
// 5. test:
// "curl -v --socks5 127.0.0.1:9011 https://www.baidu.com" => ok
// make firefox browser's port 9011 => ok
// local port listenner thread
void* thread_fun1(void* val);
// remote server listenner thread
void* thread_fun2(void* val);
// listen to the local port
void Socks5Server::listenLocal(){
this->sockfd=socket(AF_INET, SOCK_STREAM, 0);
/* bind the local address, so that the cliend can send to server */
bzero((char *)&(this->serv_addr), sizeof(this->serv_addr));
(this->serv_addr).sin_family = AF_INET;
(this->serv_addr).sin_addr.s_addr = htonl(INADDR_ANY);
(this->serv_addr).sin_port = htons(this->port);
// bind
while( bind(this->sockfd, (struct sockaddr *) &(this->serv_addr), sizeof(this->serv_addr)) < 0){
sleep(1) ;
cout << "bind fail" << endl ;
};
listen(this->sockfd,10);
};
// waiting for the local port's connection
int Socks5Server::acceptLocal(){
int newsockfd;
struct sockaddr_in cli_addr;
int cli_len=sizeof(cli_addr);
cout<<"Waitting connection from localhost..."<<endl;
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&cli_len);
if (newsockfd < 0) {
cout<<"can't bind local address"<<endl;
}else{
cout<<"Acceptted a connection from localhost"<<endl;
}
return newsockfd;
};
// a headshake for the sub-negotiation method
int Socks5Server::negotShake(int val){
// right flag, the loop is going on when th flag==0
int flag=0;
// newsockfd
int newsockfd = val;
//Get 2 bytes of information from the client
// - socks version number, total number of negotiation methods
char buf1[1];
char buf2[2];
if (recv(newsockfd, buf2, 2, 0) == -1) {
cout<<"cannot get version-nmethod"<<endl;
}
if ((uint8_t)buf2[0] != this->socks_vision) {
cout<<"socks version is wrong"<<endl;
close(newsockfd);
flag=1;
return flag;
}
if ((uint8_t)buf2[1] <= 0) {
cout<<"nmethod is wrong"<<endl;
close(newsockfd);
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++) {
recv(newsockfd, buf1, 1, 0);
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;
close(newsockfd);
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 (send(newsockfd, msg2, 2, 0) == -1) {
cout<<"cannot send socks-methond-reply"<<endl;
}
return flag;
};
// a headshake for the connection information
// to remote server
pair<int,int> Socks5Server::connShake(int val){
// right flag, the loop is going on when th flag==0
int flag=0;
// newsockfd
int newsockfd = val;
//Get the first four bytes of information
// such as the address type of URL request
// from the client
char buf4[4];
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);
flag=1;
return make_pair(1,1);
}
uint8_t cmd = (uint8_t)buf4[1];
if(cmd!=1){
cout<<"cmd is not 1"<<endl;
close(newsockfd);
flag=1;
return make_pair(1,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;
int remote_addr_length=4;
if (addressType == 1) {//ipv4
r_address=new char[4];
if (recv(newsockfd, r_address, 4, 0) == -1) {
cout<<"cannot get the ipv4\n"<<endl;
}
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;
close(newsockfd);
flag=1;
return make_pair(1,1);
}
//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);
flag=1;
return make_pair(1,1);
}
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;
struct sockaddr_in remote_addr;
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){
memcpy(&(remote_addr.sin_addr.s_addr),domin_address,remote_addr_length);
}
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);
flag=1;
}
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);
}
}
else {
printf("cmd is not connection\n");
close(newsockfd);
flag=1;
}
//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);
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 (send(newsockfd, connRrt, 10, 0) == -1) {
printf("cannot send url-reply\n");
flag=1;
}
}
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");
flag=1;
}
}
return make_pair(remote_sockfd,flag);
};
// data transmission shake
void Socks5Server::transData(pair<int,int> pairval){
int newsockfd = pairval.first;
int remote_sockfd = pairval.second;
printf("Data transmission is beginning.\n");
struct mypara
{
int para1;//参数1
int para2;//参数2
};
struct mypara pstru={newsockfd,remote_sockfd};
// listen to the local port
pthread_t tid1 ;
int ret1 = pthread_create(&tid1,NULL,thread_fun1,&(pstru));
cout<<"thread return1: "<<ret1<<endl;
// listen to the remote server
pthread_t tid2 ;
int ret2 = pthread_create(&tid2,NULL,thread_fun2,&(pstru));
cout<<"thread return2: "<<ret2<<endl;
};
// forever listenner function
void Socks5Server::forever(){
while(true){
int newsockfd = this->acceptLocal();
if(this->negotShake(newsockfd)>0){
cout<<"negotShake error"<<endl;
continue;
}
pair<int,int> pairval=connShake(newsockfd);
if(pairval.second>0){
cout<<"connShake error"<<endl;
continue;
}
int remote_sockfd = pairval.first;
this->transData(make_pair(newsockfd,remote_sockfd));
}
};
// server start
void Socks5Server::start(){
this->listenLocal();
this->forever();
close(this->sockfd);
};
// transfer data form local port to remote server
void * thread_fun1(void* val){
struct mypara
{
int para1;//参数1
int para2;//参数2
};
mypara *pstru;
pstru = (struct mypara *) val;
// pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = pstru->para1;
int remote_sockfd= pstru->para2;
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(local_sockfd, data, sizeof(data), 0);
cout << "recv from local_sock 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 ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
return NULL;
}
// transfer data form remote server to local port
void * thread_fun2(void* val){
struct mypara
{
int para1;//参数1
int para2;//参数2
};
mypara *pstru;
pstru = (struct mypara *) val;
// pair<int,int> pairval=*((pair<int,int>*)val);
int local_sockfd = pstru->para1;
int remote_sockfd= pstru->para2;
char data[MAX_SIZE];
int datalen;
int send_len = 0 ;
while(true){
datalen=recv(remote_sockfd, data, sizeof(data), 0);
cout << "recv from remote_sock datalen = " << datalen << endl ;
if (datalen <= 0) {
//nothing
break;
}else{
// send to localhost
send_len = send(local_sockfd, data, datalen, 0) ;
cout << "send to local_sockfd len = " << send_len << endl ;
}
}
close(local_sockfd) ;
close(remote_sockfd) ;
return NULL;
}
+69
View File
@@ -0,0 +1,69 @@
#ifndef SOCKS_H_INCLUDED
#define SOCKS_H_INCLUDED
#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>
#include <pthread.h>
#define SERV_TCP_PORT 9011 /* Local listening port number */
#define MAX_SIZE 1024*5120
#define SOCKS5_VERSION 5
#define THREAD_NUMBER 10
using namespace std;
class Socks5Server{
public:
// sockfd
int sockfd;
// sockaddr
struct sockaddr_in serv_addr;
/* Local listening port number */
int port;
// socks version
uint8_t socks_vision;
// 2 commom numbers
uint8_t ui0;
uint8_t ui5;
public:
// construction function
Socks5Server(){
this->port=SERV_TCP_PORT;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
}
Socks5Server(int port){
this->port=port;
this->ui0=0;
this->ui5=5;
this->socks_vision=SOCKS5_VERSION;
}
~Socks5Server(){
}
// listen to the local port
void listenLocal();
// waiting for the local port's connection
int acceptLocal();
// a headshake for the sub-negotiation method
int negotShake(int val);
// a headshake for the connection information
// to remote server
pair<int,int> connShake(int val);
// data transmission shake
void transData(pair<int,int> pairval);
// forever listenner function
void forever();
// server start
void start();
};
#endif
Binary file not shown.
+10
View File
@@ -0,0 +1,10 @@
#include "Socks5Server.h"
using namespace std;
int main(){
// new a server
Socks5Server *ss_server=new Socks5Server();
// server start
ss_server->start();
// delete
delete ss_server;
}
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More