mirror of
https://github.com/rofl0r/proxychains-ng
synced 2025-01-23 09:33:00 +08:00
separate functions, add utils, hook recvmsg
This commit is contained in:
parent
45aed8644f
commit
8ed4b52140
330
src/core.c
330
src/core.c
@ -633,13 +633,13 @@ int read_udp_header(char * buf, size_t buflen, socks5_addr* src_addr, unsigned s
|
|||||||
case ATYP_V6:
|
case ATYP_V6:
|
||||||
PDEBUG("UDP header with ATYP_V4/6 addr type\n");
|
PDEBUG("UDP header with ATYP_V4/6 addr type\n");
|
||||||
v6 = src_addr->atyp == ATYP_V6;
|
v6 = src_addr->atyp == ATYP_V6;
|
||||||
PDEBUG("buflen : %d\n", buflen);
|
|
||||||
if(buflen < (4 + 2 + v6?16:4) ){
|
if(buflen < (4 + 2 + v6?16:4) ){
|
||||||
PDEBUG("buffer too short to read the UDP header\n");
|
PDEBUG("buffer too short to read the UDP header\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(src_addr->addr.v6, buf + buf_iter, v6?16:4);
|
memcpy(src_addr->addr.v6, buf + buf_iter, v6?16:4);
|
||||||
buf_iter += v6?16:4;
|
buf_iter += v6?16:4;
|
||||||
|
cast_socks5addr_v4inv6_to_v4(src_addr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -651,7 +651,186 @@ int read_udp_header(char * buf, size_t buflen, socks5_addr* src_addr, unsigned s
|
|||||||
return buf_iter;
|
return buf_iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
int receive_udp_packet(int sockfd, udp_relay_chain chain, ip_type* src_addr, unsigned short* src_port, char* data, unsigned int data_len ){
|
size_t get_iov_total_len(struct iovec* iov, size_t iov_len){
|
||||||
|
size_t n = 0;
|
||||||
|
for(int i=0; i<iov_len; i++){
|
||||||
|
n += iov[i].iov_len;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t write_buf_to_iov(void* buff, size_t buff_len, struct iovec* iov, size_t iov_len){
|
||||||
|
size_t written = 0;
|
||||||
|
int i = 0;
|
||||||
|
size_t min = 0;
|
||||||
|
//size_t iov_total_len = get_iov_total_len(iov, iov_len);
|
||||||
|
|
||||||
|
while( (written < buff_len) && (i < iov_len)){
|
||||||
|
min = ((buff_len-written)<iov[i].iov_len)?(buff_len-written):iov[i].iov_len;
|
||||||
|
memcpy(iov[i].iov_base, buff+written, min);
|
||||||
|
written += min;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cast_socks5addr_v4inv6_to_v4(socks5_addr* addr){
|
||||||
|
if( (addr->atyp == ATYP_V6) && !memcmp(addr->addr.v6, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12)){
|
||||||
|
PDEBUG("casting v4inv6 address to v4 address\n");
|
||||||
|
addr->atyp=ATYP_V4;
|
||||||
|
memcpy(addr->addr.v4.octet, addr->addr.v6+12, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int compare_iptype_sockaddr(ip_type addr1, struct sockaddr addr2){
|
||||||
|
if(addr1.is_v6 && (((struct sockaddr_in6 *) &(addr2))->sin6_family == AF_INET6)){
|
||||||
|
//Both are IPv6
|
||||||
|
return !memcmp(((struct sockaddr_in6 *)&addr2)->sin6_addr.s6_addr, addr1.addr.v6, 16);
|
||||||
|
} else if(!addr1.is_v6 && (((struct sockaddr_in *) &(addr2))->sin_family == AF_INET)){
|
||||||
|
//Both are IPv4
|
||||||
|
return ((uint32_t)(((struct sockaddr_in *)&addr2)->sin_addr.s_addr) == addr1.addr.v4.as_int);
|
||||||
|
} else {
|
||||||
|
// Not the same address type
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int compare_socks5_addr_iptype(socks5_addr addr1, ip_type addr2){
|
||||||
|
PFUNC();
|
||||||
|
if(addr1.atyp == ATYP_DOM){
|
||||||
|
//addr1 is a domain name
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr1.atyp == ATYP_V6) && addr2.is_v6){
|
||||||
|
//Both are IPv6
|
||||||
|
return !memcmp(addr1.addr.v6, addr2.addr.v6, 16);
|
||||||
|
} else if((addr1.atyp == ATYP_V4) && !addr2.is_v6){
|
||||||
|
//Both are IPv4
|
||||||
|
return (addr1.addr.v4.as_int == addr2.addr.v4.as_int);
|
||||||
|
} else {
|
||||||
|
// Not the same address type
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_from_chain_head(udp_relay_chain chain, struct sockaddr src_addr){
|
||||||
|
|
||||||
|
if(compare_iptype_sockaddr(chain.head->bnd_addr, src_addr)){
|
||||||
|
return (chain.head->bnd_port == ((struct sockaddr_in*)&src_addr)->sin_port);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int decapsulate_check_udp_packet(void* in_buffer, size_t in_buffer_len, udp_relay_chain chain, socks5_addr* src_addr, unsigned short* src_port, void* udp_data, size_t* udp_data_len){
|
||||||
|
|
||||||
|
PFUNC();
|
||||||
|
// Go through the whole proxy chain, decapsulate each header and check that the addresses match
|
||||||
|
|
||||||
|
udp_relay_node * tmp = chain.head;
|
||||||
|
int read = 0;
|
||||||
|
int rc = 0;
|
||||||
|
socks5_addr header_addr;
|
||||||
|
unsigned short header_port;
|
||||||
|
char header_frag;
|
||||||
|
while (tmp->next != NULL)
|
||||||
|
{
|
||||||
|
rc = read_udp_header(in_buffer+read, in_buffer_len-read, &header_addr, &header_port, &header_frag );
|
||||||
|
if(-1 == rc){
|
||||||
|
PDEBUG("error reading UDP header\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
read += rc;
|
||||||
|
|
||||||
|
if(header_frag != 0x00){
|
||||||
|
printf("WARNING: received UDP packet with frag != 0 while fragmentation is unsupported.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!compare_socks5_addr_iptype(header_addr, tmp->next->bnd_addr)){
|
||||||
|
PDEBUG("UDP header addr is not equal to proxy node addr, dropping packet\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tmp->next->bnd_port != header_port){
|
||||||
|
PDEBUG("UDP header port is not equal to proxy node port, dropping packet\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDEBUG("UDP header's addr and port correspond to proxy node's addr and port\n");
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDEBUG("all UDP headers validated\n");
|
||||||
|
|
||||||
|
|
||||||
|
// Decapsulate the last header. No checks needed here, just pass the source addr and port as return values
|
||||||
|
rc = read_udp_header(in_buffer+read, in_buffer_len-read, src_addr, src_port, &header_frag);
|
||||||
|
if(-1 == rc){
|
||||||
|
PDEBUG("error reading UDP header\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
read += rc;
|
||||||
|
|
||||||
|
if(header_frag != 0x00){
|
||||||
|
printf("WARNING: received UDP packet with frag != 0 while fragmentation is unsupported.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Copy the UDP data to the provided buffer. If the provided buffer is too small, data is truncated
|
||||||
|
int min = ((in_buffer_len-read)>*udp_data_len)?*udp_data_len:(in_buffer_len-read);
|
||||||
|
memcpy(udp_data,in_buffer+read, min);
|
||||||
|
|
||||||
|
// Write back the length of written UDP data in the input/output parameter udp_data_len
|
||||||
|
*udp_data_len = min;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unsocks_udp_packet(void* in_buffer, size_t in_buffer_len, udp_relay_chain chain, ip_type* src_ip, unsigned short* src_port, void* udp_data, size_t* udp_data_len){
|
||||||
|
PFUNC();
|
||||||
|
// Decapsulate all the UDP headers and check that the packet came from the right proxy nodes
|
||||||
|
int rc;
|
||||||
|
socks5_addr src_addr;
|
||||||
|
rc = decapsulate_check_udp_packet(in_buffer, in_buffer_len, chain, &src_addr, src_port, udp_data, udp_data_len);
|
||||||
|
if(rc != SUCCESS){
|
||||||
|
PDEBUG("error decapsulating the packet\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
PDEBUG("all UDP headers decapsulated and validated\n");
|
||||||
|
|
||||||
|
// If the innermost UDP header (containing the address of the final target) is of type ATYP_DOM, perform a
|
||||||
|
// reverse mapping to hand the 224.X.X.X IP to the client application
|
||||||
|
|
||||||
|
if(src_addr.atyp == ATYP_DOM){
|
||||||
|
PDEBUG("Fetching matching IP for hostname\n");
|
||||||
|
DUMP_BUFFER(src_addr.addr.dom.name,src_addr.addr.dom.len);
|
||||||
|
ip_type4 tmp_ip = IPT4_INVALID;
|
||||||
|
char host_string[256];
|
||||||
|
memcpy(host_string, src_addr.addr.dom.name, src_addr.addr.dom.len);
|
||||||
|
host_string[src_addr.addr.dom.len] = 0x00;
|
||||||
|
|
||||||
|
tmp_ip = rdns_get_ip_for_host(host_string, src_addr.addr.dom.len);
|
||||||
|
if(tmp_ip.as_int == -1){
|
||||||
|
PDEBUG("error getting ip for host\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
src_addr.atyp = ATYP_V4;
|
||||||
|
src_addr.addr.v4.as_int = tmp_ip.as_int;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
src_ip->is_v6 = (src_addr.atyp == ATYP_V6);
|
||||||
|
if(src_ip->is_v6){
|
||||||
|
memcpy(src_ip->addr.v6, src_addr.addr.v6, 16);
|
||||||
|
} else{
|
||||||
|
src_ip->addr.v4.as_int = src_addr.addr.v4.as_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int receive_udp_packet(int sockfd, udp_relay_chain chain, ip_type* src_ip, unsigned short* src_port, char* data, unsigned int data_len ){
|
||||||
//receives data on sockfd, decapsulates the header for each relay in chain and check they match, returns UDP data and source address/port
|
//receives data on sockfd, decapsulates the header for each relay in chain and check they match, returns UDP data and source address/port
|
||||||
|
|
||||||
PFUNC();
|
PFUNC();
|
||||||
@ -671,129 +850,68 @@ int receive_udp_packet(int sockfd, udp_relay_chain chain, ip_type* src_addr, uns
|
|||||||
PDEBUG("successful recvfrom(), %d bytes received\n", bytes_received);
|
PDEBUG("successful recvfrom(), %d bytes received\n", bytes_received);
|
||||||
//Check that the packet was received from the first relay of the chain
|
//Check that the packet was received from the first relay of the chain
|
||||||
// i.e. does from == chain.head.bnd_addr ?
|
// i.e. does from == chain.head.bnd_addr ?
|
||||||
int from_isv6 = ((struct sockaddr_in *) &(from))->sin_family == AF_INET6;
|
|
||||||
int same_address = 0;
|
|
||||||
int same_port = 0;
|
|
||||||
|
|
||||||
if(chain.head->bnd_addr.is_v6){
|
if(!is_from_chain_head(chain, from)){
|
||||||
if(from_isv6){
|
|
||||||
same_address = memcmp(((struct sockaddr_in6 *)&from)->sin6_addr.s6_addr, chain.head->bnd_addr.addr.v6, 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
uint32_t from_v4_asint;
|
|
||||||
if(from_isv6){
|
|
||||||
// Maybe from is a ipv4-mapped ipv6 ? // TODO: use the existing is_v4inv6 as in connect and sendto
|
|
||||||
memcpy(from_v4_asint, ((struct sockaddr_in6 *)&from)->sin6_addr.s6_addr + 11, 4);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
from_v4_asint = (uint32_t)(((struct sockaddr_in *)&from)->sin_addr.s_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
same_address = from_v4_asint == chain.head->bnd_addr.addr.v4.as_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
same_port = chain.head->bnd_port == from_isv6?((struct sockaddr_in6 *)&from)->sin6_port:((struct sockaddr_in *)&from)->sin_port;
|
|
||||||
|
|
||||||
if(!(same_address && same_port)){
|
|
||||||
PDEBUG("UDP packet not received from the proxy chain's head, transfering it as is\n");
|
PDEBUG("UDP packet not received from the proxy chain's head, transfering it as is\n");
|
||||||
int min = (bytes_received <= data_len)?bytes_received:data_len;
|
int min = (bytes_received <= data_len)?bytes_received:data_len;
|
||||||
|
//TODO : il faut aussi transmettre les adresses et ports qu ón a recu a l'appli qui a fait le call !!!!!
|
||||||
memcpy(data, buffer, min);
|
memcpy(data, buffer, min);
|
||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDEBUG("packet received from the proxy chain's head\n");
|
PDEBUG("packet received from the proxy chain's head\n");
|
||||||
// Go through the whole proxy chain, decapsulate each header and check that the addresses match
|
|
||||||
|
|
||||||
udp_relay_node * tmp = chain.head;
|
int rc;
|
||||||
int read = 0;
|
size_t udp_data_len = data_len;
|
||||||
int rc = 0;
|
rc = unsocks_udp_packet(buffer, bytes_received, chain, src_ip, src_port, data, &udp_data_len);
|
||||||
socks5_addr header_addr;
|
if(rc != SUCCESS){
|
||||||
unsigned short header_port;
|
PDEBUG("error unSOCKSing the UDP packet\n");
|
||||||
char header_frag;
|
|
||||||
while (tmp->next != NULL)
|
|
||||||
{
|
|
||||||
same_address = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
rc = read_udp_header(buffer+read, bytes_received-read, &header_addr, &header_port, &header_frag );
|
|
||||||
if(-1 == rc){
|
|
||||||
PDEBUG("error reading UDP header\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
read += rc;
|
|
||||||
|
|
||||||
int header_v6 = header_addr.atyp == ATYP_V6;
|
|
||||||
|
|
||||||
if(tmp->next->bnd_port != header_port){
|
|
||||||
PDEBUG("UDP header port is not equal to proxy node port, dropping packet\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tmp->next->bnd_addr.is_v6){
|
|
||||||
if(header_v6){
|
|
||||||
same_address = memcmp(tmp->next->bnd_addr.addr.v6, header_addr.addr.v6, 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
same_address = memcmp(&(tmp->next->bnd_addr.addr.v4), header_v6?(&(header_addr.addr.v6)+11):&(header_addr.addr.v4), 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(!same_address){
|
|
||||||
PDEBUG("UDP header addr is not equal to proxy node addr, dropping packet\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PDEBUG("UDP header's addr and port correspond to proxy node's addr and port\n");
|
|
||||||
tmp = tmp->next;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
PDEBUG("all UDP headers validated\n");
|
|
||||||
|
|
||||||
|
|
||||||
// Decapsulate the last header. No checks needed here, just pass the source addr and port as return values
|
|
||||||
char frag;
|
|
||||||
rc = read_udp_header(buffer+read, bytes_received-read, &header_addr, src_port, &frag);
|
|
||||||
if(-1 == rc){
|
|
||||||
PDEBUG("error reading UDP header\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
read += rc;
|
PDEBUG("UDP packet successfully unSOCKified\n");
|
||||||
|
|
||||||
if(header_addr.atyp == ATYP_DOM){ // do the reverse mapping
|
return udp_data_len;
|
||||||
PDEBUG("Fetching matching IP for hostname\n");
|
|
||||||
DUMP_BUFFER(header_addr.addr.dom.name,header_addr.addr.dom.len);
|
|
||||||
ip_type4 tmp_ip = IPT4_INVALID;
|
|
||||||
char host_string[256];
|
|
||||||
memcpy(host_string, header_addr.addr.dom.name, header_addr.addr.dom.len);
|
|
||||||
host_string[header_addr.addr.dom.len] = 0x00;
|
|
||||||
|
|
||||||
tmp_ip = rdns_get_ip_for_host(host_string, header_addr.addr.dom.len);
|
// // Decapsulate all the UDP headers and check that the packet came from the right proxy nodes
|
||||||
if(tmp_ip.as_int == -1){
|
// int rc;
|
||||||
PDEBUG("No matching IP found for hostname\n");
|
// socks5_addr src_addr;
|
||||||
return -1;
|
// size_t udp_data_len = data_len;
|
||||||
}
|
// rc = decapsulate_check_udp_packet(buffer, bytes_received, chain, &src_addr, src_port, data, &udp_data_len);
|
||||||
header_addr.atyp = ATYP_V4;
|
// if(rc != SUCCESS){
|
||||||
header_addr.addr.v4.as_int = tmp_ip.as_int;
|
// PDEBUG("error decapsulating the packet\n");
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
// PDEBUG("all UDP headers decapsulated and validated\n");
|
||||||
|
|
||||||
}
|
// // If the innermost UDP header (containing the address of the final target) is of type ATYP_DOM, perform a
|
||||||
|
// // reverse mapping to hand the 224.X.X.X IP to the client application
|
||||||
|
|
||||||
src_addr->is_v6 = (header_addr.atyp == ATYP_V6);
|
// if(src_addr.atyp == ATYP_DOM){
|
||||||
if(src_addr->is_v6){
|
// PDEBUG("Fetching matching IP for hostname\n");
|
||||||
memcpy(src_addr->addr.v6, header_addr.addr.v6, 16);
|
// DUMP_BUFFER(src_addr.addr.dom.name,src_addr.addr.dom.len);
|
||||||
} else{
|
// ip_type4 tmp_ip = IPT4_INVALID;
|
||||||
src_addr->addr.v4.as_int = header_addr.addr.v4.as_int;
|
// char host_string[256];
|
||||||
}
|
// memcpy(host_string, src_addr.addr.dom.name, src_addr.addr.dom.len);
|
||||||
|
// host_string[src_addr.addr.dom.len] = 0x00;
|
||||||
|
|
||||||
|
// tmp_ip = rdns_get_ip_for_host(host_string, src_addr.addr.dom.len);
|
||||||
|
// if(tmp_ip.as_int == -1){
|
||||||
|
// PDEBUG("error getting ip for host\n");
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
// src_addr.atyp = ATYP_V4;
|
||||||
|
// src_addr.addr.v4.as_int = tmp_ip.as_int;
|
||||||
|
|
||||||
int min = ((bytes_received-read)>data_len)?data_len:(bytes_received-read);
|
// }
|
||||||
memcpy(data,buffer+read, min);
|
|
||||||
|
|
||||||
|
// src_ip->is_v6 = (src_addr.atyp == ATYP_V6);
|
||||||
|
// if(src_ip->is_v6){
|
||||||
|
// memcpy(src_ip->addr.v6, src_addr.addr.v6, 16);
|
||||||
|
// } else{
|
||||||
|
// src_ip->addr.v4.as_int = src_addr.addr.v4.as_int;
|
||||||
|
// }
|
||||||
|
|
||||||
return min;
|
// return udp_data_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_udp_packet(int sockfd, udp_relay_chain chain, ip_type target_ip, unsigned short target_port, char frag, char * data, unsigned int data_len) {
|
int send_udp_packet(int sockfd, udp_relay_chain chain, ip_type target_ip, unsigned short target_port, char frag, char * data, unsigned int data_len) {
|
||||||
|
11
src/core.h
11
src/core.h
@ -103,7 +103,6 @@ typedef enum {
|
|||||||
} ATYP;
|
} ATYP;
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
ATYP atyp;
|
|
||||||
union {
|
union {
|
||||||
ip_type4 v4;
|
ip_type4 v4;
|
||||||
unsigned char v6[16];
|
unsigned char v6[16];
|
||||||
@ -112,6 +111,7 @@ typedef struct{
|
|||||||
char name[255];
|
char name[255];
|
||||||
} dom;
|
} dom;
|
||||||
} addr ;
|
} addr ;
|
||||||
|
ATYP atyp;
|
||||||
} socks5_addr;
|
} socks5_addr;
|
||||||
|
|
||||||
/* A structure to hold necessary information about an UDP relay server that has been set up
|
/* A structure to hold necessary information about an UDP relay server that has been set up
|
||||||
@ -170,6 +170,9 @@ typedef ssize_t (*recv_t) (int sockfd, void *buf, size_t len, int flags);
|
|||||||
typedef ssize_t (*recvfrom_t) (int sockfd, void *buf, size_t len, int flags,
|
typedef ssize_t (*recvfrom_t) (int sockfd, void *buf, size_t len, int flags,
|
||||||
struct sockaddr *src_addr, socklen_t *addrlen);
|
struct sockaddr *src_addr, socklen_t *addrlen);
|
||||||
|
|
||||||
|
typedef ssize_t (*sendmsg_t) (int sockfd, const struct msghdr *msg, int flags);
|
||||||
|
typedef ssize_t (*recvmsg_t) (int sockfd, struct msghdr *msg, int flags);
|
||||||
|
|
||||||
|
|
||||||
extern connect_t true_connect;
|
extern connect_t true_connect;
|
||||||
extern gethostbyname_t true_gethostbyname;
|
extern gethostbyname_t true_gethostbyname;
|
||||||
@ -181,6 +184,8 @@ extern sendto_t true_sendto;
|
|||||||
extern recvfrom_t true_recvfrom;
|
extern recvfrom_t true_recvfrom;
|
||||||
extern recv_t true_recv;
|
extern recv_t true_recv;
|
||||||
extern send_t true_send;
|
extern send_t true_send;
|
||||||
|
extern sendmsg_t true_sendmsg;
|
||||||
|
extern recvmsg_t true_recvmsg;
|
||||||
|
|
||||||
struct gethostbyname_data {
|
struct gethostbyname_data {
|
||||||
struct hostent hostent_space;
|
struct hostent hostent_space;
|
||||||
@ -207,6 +212,10 @@ int free_relay_chain_nodes(udp_relay_chain chain);
|
|||||||
udp_relay_chain * open_relay_chain(proxy_data *pd, unsigned int proxy_count, chain_type ct, unsigned int max_chains);
|
udp_relay_chain * open_relay_chain(proxy_data *pd, unsigned int proxy_count, chain_type ct, unsigned int max_chains);
|
||||||
int send_udp_packet(int sockfd, udp_relay_chain chain, ip_type target_ip, unsigned short target_port, char frag, char * data, unsigned int data_len);
|
int send_udp_packet(int sockfd, udp_relay_chain chain, ip_type target_ip, unsigned short target_port, char frag, char * data, unsigned int data_len);
|
||||||
int receive_udp_packet(int sockfd, udp_relay_chain chain, ip_type* src_addr, unsigned short* src_port, char* data, unsigned int data_len );
|
int receive_udp_packet(int sockfd, udp_relay_chain chain, ip_type* src_addr, unsigned short* src_port, char* data, unsigned int data_len );
|
||||||
|
size_t get_msg_iov_total_len(struct iovec* iov, size_t iov_len);
|
||||||
|
size_t write_buf_to_iov(void* buff, size_t buff_len, struct iovec* iov, size_t iov_len);
|
||||||
|
int is_from_chain_head(udp_relay_chain chain, struct sockaddr src_addr);
|
||||||
|
int unsocks_udp_packet(void* in_buffer, size_t in_buffer_len, udp_relay_chain chain, ip_type* src_ip, unsigned short* src_port, void* udp_data, size_t* udp_data_len);
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -67,6 +67,8 @@ sendto_t true_sendto;
|
|||||||
send_t true_send;
|
send_t true_send;
|
||||||
recv_t true_recv;
|
recv_t true_recv;
|
||||||
recvfrom_t true_recvfrom;
|
recvfrom_t true_recvfrom;
|
||||||
|
sendmsg_t true_sendmsg;
|
||||||
|
recvmsg_t true_recvmsg;
|
||||||
|
|
||||||
int tcp_read_time_out;
|
int tcp_read_time_out;
|
||||||
int tcp_connect_time_out;
|
int tcp_connect_time_out;
|
||||||
@ -810,10 +812,13 @@ HOOKFUNC(int, getaddrinfo, const char *node, const char *service, const struct a
|
|||||||
INIT();
|
INIT();
|
||||||
PDEBUG("getaddrinfo: %s %s\n", node ? node : "null", service ? service : "null");
|
PDEBUG("getaddrinfo: %s %s\n", node ? node : "null", service ? service : "null");
|
||||||
|
|
||||||
if(proxychains_resolver != DNSLF_LIBC)
|
if(proxychains_resolver != DNSLF_LIBC){
|
||||||
|
PDEBUG("using proxy_getaddrinfo()\n");
|
||||||
return proxy_getaddrinfo(node, service, hints, res);
|
return proxy_getaddrinfo(node, service, hints, res);
|
||||||
else
|
}
|
||||||
|
else{
|
||||||
return true_getaddrinfo(node, service, hints, res);
|
return true_getaddrinfo(node, service, hints, res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HOOKFUNC(void, freeaddrinfo, struct addrinfo *res) {
|
HOOKFUNC(void, freeaddrinfo, struct addrinfo *res) {
|
||||||
@ -1026,6 +1031,185 @@ HOOKFUNC(ssize_t, sendto, int sockfd, const void *buf, size_t len, int flags,
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HOOKFUNC(ssize_t, sendmsg, int sockfd, const struct msghdr *msg, int flags){
|
||||||
|
// //TODO hugoc
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
HOOKFUNC(ssize_t, recvmsg, int sockfd, struct msghdr *msg, int flags){
|
||||||
|
|
||||||
|
|
||||||
|
INIT();
|
||||||
|
PFUNC();
|
||||||
|
|
||||||
|
int socktype = 0;
|
||||||
|
socklen_t optlen = 0;
|
||||||
|
optlen = sizeof(socktype);
|
||||||
|
getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &socktype, &optlen);
|
||||||
|
if( socktype != SOCK_DGRAM){
|
||||||
|
PDEBUG("sockfd %d is not a SOCK_DGRAM socket, returning to true_recvmsg\n", sockfd);
|
||||||
|
return true_recvmsg(sockfd, msg, flags);
|
||||||
|
}
|
||||||
|
PDEBUG("sockfd %d is a SOCK_DGRAM socket\n", sockfd);
|
||||||
|
|
||||||
|
struct sockaddr addr;
|
||||||
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
if(SUCCESS != getsockname(sockfd, &addr, &addr_len )){
|
||||||
|
PDEBUG("error getsockname, errno=%d. Returning to true_recvmsg()\n", errno);
|
||||||
|
return true_recvmsg(sockfd,msg, flags);
|
||||||
|
}
|
||||||
|
sa_family_t fam = SOCKFAMILY(addr);
|
||||||
|
if(!(fam == AF_INET || fam == AF_INET6)){
|
||||||
|
PDEBUG("sockfd %d address familiy is not a AF_INET or AF_INET6, returning to true_recvmsg\n", sockfd);
|
||||||
|
return true_recvmsg(sockfd,msg, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDEBUG("sockfd %d's address family is AF_INET or AF_INET6\n", sockfd);
|
||||||
|
|
||||||
|
udp_relay_chain* relay_chain = get_relay_chain(relay_chains, sockfd);
|
||||||
|
if(relay_chain == NULL){
|
||||||
|
// No chain is opened for this socket
|
||||||
|
PDEBUG("sockfd %d does not corresponds to any opened relay chain, returning to true_recvmsg\n", sockfd);
|
||||||
|
return true_recvmsg(sockfd,msg, flags);
|
||||||
|
}
|
||||||
|
PDEBUG("sockfd %d is associated with udp_relay_chain %x\n", sockfd, relay_chain);
|
||||||
|
|
||||||
|
|
||||||
|
char buffer[65535]; //buffer to receive and decapsulate a UDP relay packet. UDP maxsize is 65535
|
||||||
|
size_t bytes_received;
|
||||||
|
|
||||||
|
struct sockaddr from;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct iovec iov[1];
|
||||||
|
iov[0].iov_base = buffer;
|
||||||
|
iov[0].iov_len = sizeof(buffer);
|
||||||
|
|
||||||
|
|
||||||
|
struct msghdr tmp_msg;
|
||||||
|
|
||||||
|
tmp_msg.msg_name = &from;
|
||||||
|
tmp_msg.msg_namelen = sizeof(from);
|
||||||
|
tmp_msg.msg_iov = iov;
|
||||||
|
tmp_msg.msg_iovlen = 1;
|
||||||
|
tmp_msg.msg_control = msg->msg_control; // Pass directly
|
||||||
|
tmp_msg.msg_controllen = msg->msg_controllen; // Pass directly
|
||||||
|
tmp_msg.msg_flags = msg->msg_flags;
|
||||||
|
|
||||||
|
PDEBUG("exec true_recvmsg\n");
|
||||||
|
bytes_received = true_recvmsg(sockfd, &tmp_msg, flags);
|
||||||
|
if(-1 == bytes_received){
|
||||||
|
PDEBUG("true_recvmsg returned -1\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer the fields we do not manage
|
||||||
|
|
||||||
|
msg->msg_controllen = tmp_msg.msg_controllen;
|
||||||
|
msg->msg_control = tmp_msg.msg_control; //Not sure this one is necessary
|
||||||
|
msg->msg_flags = tmp_msg.msg_flags;
|
||||||
|
|
||||||
|
PDEBUG("successful recvmsg(), %d bytes received\n", bytes_received);
|
||||||
|
//Check that the packet was received from the first relay of the chain
|
||||||
|
|
||||||
|
if(!is_from_chain_head(*relay_chain, *(struct sockaddr *)(msg->msg_name))){
|
||||||
|
PDEBUG("UDP packet not received from the proxy chain's head, transfering it as is\n");
|
||||||
|
// Write the data we received in tmp_msg to msg
|
||||||
|
int written = write_buf_to_iov(buffer, bytes_received, msg->msg_iov, msg->msg_iovlen);
|
||||||
|
|
||||||
|
// Write the addr we received in tmp_msg to msg
|
||||||
|
if(msg->msg_name != NULL){
|
||||||
|
socklen_t min = (msg->msg_namelen>tmp_msg.msg_namelen)?tmp_msg.msg_namelen:msg->msg_namelen;
|
||||||
|
memcpy(msg->msg_name, tmp_msg.msg_name, min);
|
||||||
|
msg->msg_namelen = min;
|
||||||
|
}
|
||||||
|
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDEBUG("packet received from the proxy chain's head\n");
|
||||||
|
|
||||||
|
|
||||||
|
int rc;
|
||||||
|
ip_type src_ip;
|
||||||
|
unsigned short src_port;
|
||||||
|
char udp_data[65535];
|
||||||
|
size_t udp_data_len = sizeof(udp_data);
|
||||||
|
|
||||||
|
rc = unsocks_udp_packet(buffer, bytes_received, *relay_chain, &src_ip, &src_port, udp_data, &udp_data_len);
|
||||||
|
if(rc != SUCCESS){
|
||||||
|
PDEBUG("error unSOCKSing the UDP packet\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
PDEBUG("UDP packet successfully unSOCKified\n");
|
||||||
|
|
||||||
|
|
||||||
|
/*debug*/
|
||||||
|
DEBUGDECL(char str[256]);
|
||||||
|
PDEBUG("received %d bytes through receive_udp_packet()\n", udp_data_len);
|
||||||
|
PDEBUG("data: ");
|
||||||
|
DUMP_BUFFER(udp_data, udp_data_len);
|
||||||
|
PDEBUG("src_ip: ");
|
||||||
|
DUMP_BUFFER(src_ip.addr.v6, src_ip.is_v6?16:4);
|
||||||
|
PDEBUG("src_ip: %s\n", inet_ntop(src_ip.is_v6 ? AF_INET6 : AF_INET, src_ip.is_v6 ? (void*)src_ip.addr.v6 : (void*)src_ip.addr.v4.octet, str, sizeof(str)));
|
||||||
|
PDEBUG("from_port: %hu\n", ntohs(src_port));
|
||||||
|
/*end debug*/
|
||||||
|
|
||||||
|
|
||||||
|
// Write the udp data we received in tmp_msg and unsocksified to msg
|
||||||
|
int written = write_buf_to_iov(udp_data, udp_data_len, msg->msg_iov, msg->msg_iovlen);
|
||||||
|
|
||||||
|
// Overwrite the addresse in msg with the src_addr retrieved from unsocks_udp_packet();
|
||||||
|
|
||||||
|
if(msg->msg_name != NULL){
|
||||||
|
struct sockaddr_in* src_addr_v4;
|
||||||
|
struct sockaddr_in6* src_addr_v6;
|
||||||
|
|
||||||
|
//TODO bien gérer le controle de la taille de la src_addr fournie et le retour dans addrlen
|
||||||
|
// TODO faire une fonction cast_iptype_to_sockaddr()
|
||||||
|
|
||||||
|
if(src_ip.is_v6 && is_v4inv6((struct in6_addr*)src_ip.addr.v6)){
|
||||||
|
PDEBUG("src_ip is v4 in v6 ip\n");
|
||||||
|
if(msg->msg_namelen < sizeof(struct sockaddr_in)){
|
||||||
|
PDEBUG("msg_namelen too short for ipv4\n");
|
||||||
|
}
|
||||||
|
src_addr_v4 = (struct sockaddr_in*)(msg->msg_name);
|
||||||
|
src_addr_v4->sin_family = AF_INET;
|
||||||
|
src_addr_v4->sin_port = src_port;
|
||||||
|
memcpy(&(src_addr_v4->sin_addr.s_addr), src_ip.addr.v6+12, 4);
|
||||||
|
msg->msg_namelen = sizeof(src_addr_v4);
|
||||||
|
}
|
||||||
|
else if(src_ip.is_v6){
|
||||||
|
PDEBUG("src_ip is true v6\n");
|
||||||
|
if(msg->msg_namelen < sizeof(struct sockaddr_in6)){
|
||||||
|
PDEBUG("addrlen too short for ipv6\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
src_addr_v6 = (struct sockaddr_in6*)(msg->msg_name);
|
||||||
|
src_addr_v6->sin6_family = AF_INET6;
|
||||||
|
src_addr_v6->sin6_port = src_port;
|
||||||
|
memcpy(src_addr_v6->sin6_addr.s6_addr, src_ip.addr.v6, 16);
|
||||||
|
msg->msg_namelen = sizeof(src_addr_v6);
|
||||||
|
}else {
|
||||||
|
if(msg->msg_namelen < sizeof(struct sockaddr_in)){
|
||||||
|
PDEBUG("addrlen too short for ipv4\n");
|
||||||
|
}
|
||||||
|
src_addr_v4 = (struct sockaddr_in*)(msg->msg_name);
|
||||||
|
src_addr_v4->sin_family = AF_INET;
|
||||||
|
src_addr_v4->sin_port = src_port;
|
||||||
|
src_addr_v4->sin_addr.s_addr = (in_addr_t) src_ip.addr.v4.as_int;
|
||||||
|
msg->msg_namelen = sizeof(src_addr_v4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return udp_data_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HOOKFUNC(ssize_t, recv, int sockfd, void *buf, size_t len, int flags){
|
HOOKFUNC(ssize_t, recv, int sockfd, void *buf, size_t len, int flags){
|
||||||
INIT();
|
INIT();
|
||||||
PFUNC();
|
PFUNC();
|
||||||
@ -1095,7 +1279,7 @@ HOOKFUNC(ssize_t, recvfrom, int sockfd, void *buf, size_t len, int flags,
|
|||||||
|
|
||||||
// WARNING : Est ce que si le client avait envoyé des packets UDP avec resolution DNS dans le socks,
|
// WARNING : Est ce que si le client avait envoyé des packets UDP avec resolution DNS dans le socks,
|
||||||
// on doit lui filer comme address source pour les packets recu l'addresse de mapping DNS ? Si oui comment
|
// on doit lui filer comme address source pour les packets recu l'addresse de mapping DNS ? Si oui comment
|
||||||
// la retrouver ?
|
// la retrouver ? -> done in receive_udp_packet()
|
||||||
|
|
||||||
int min = (bytes_received > len)?len:bytes_received;
|
int min = (bytes_received > len)?len:bytes_received;
|
||||||
memcpy(buf, tmp_buffer, min);
|
memcpy(buf, tmp_buffer, min);
|
||||||
@ -1197,6 +1381,8 @@ static void setup_hooks(void) {
|
|||||||
SETUP_SYM(send);
|
SETUP_SYM(send);
|
||||||
SETUP_SYM(sendto);
|
SETUP_SYM(sendto);
|
||||||
SETUP_SYM(recvfrom);
|
SETUP_SYM(recvfrom);
|
||||||
|
SETUP_SYM(recvmsg);
|
||||||
|
//SETUP_SYM(sendmsg);
|
||||||
SETUP_SYM(recv);
|
SETUP_SYM(recv);
|
||||||
SETUP_SYM(gethostbyname);
|
SETUP_SYM(gethostbyname);
|
||||||
SETUP_SYM(getaddrinfo);
|
SETUP_SYM(getaddrinfo);
|
||||||
|
Loading…
Reference in New Issue
Block a user