mirror of
https://github.com/rofl0r/proxychains-ng
synced 2025-01-08 22:22:52 +08:00
dig works
This commit is contained in:
parent
8ed4b52140
commit
f3511f80a6
2
Makefile
2
Makefile
@ -28,7 +28,7 @@ LOBJS = src/version.o \
|
||||
|
||||
GENH = src/version.h
|
||||
|
||||
CFLAGS += -Wall -O0 -g -std=c99 -D_GNU_SOURCE -pipe
|
||||
CFLAGS += -Wall -O0 -g -std=c99 -D_GNU_SOURCE -pipe -DDEBUG
|
||||
NO_AS_NEEDED = -Wl,--no-as-needed
|
||||
LDFLAGS = -fPIC $(NO_AS_NEEDED) $(LIBDL) $(PTHREAD)
|
||||
INC =
|
||||
|
361
src/core.c
361
src/core.c
@ -674,6 +674,23 @@ size_t write_buf_to_iov(void* buff, size_t buff_len, struct iovec* iov, size_t i
|
||||
return written;
|
||||
}
|
||||
|
||||
|
||||
size_t write_iov_to_buf(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(buff+written, iov[i].iov_base, 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");
|
||||
@ -723,6 +740,7 @@ int is_from_chain_head(udp_relay_chain chain, struct sockaddr src_addr){
|
||||
}
|
||||
|
||||
|
||||
|
||||
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();
|
||||
@ -787,7 +805,7 @@ int decapsulate_check_udp_packet(void* in_buffer, size_t in_buffer_len, udp_rela
|
||||
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){
|
||||
int unsocksify_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;
|
||||
@ -863,7 +881,7 @@ int receive_udp_packet(int sockfd, udp_relay_chain chain, ip_type* src_ip, unsig
|
||||
|
||||
int rc;
|
||||
size_t udp_data_len = data_len;
|
||||
rc = unsocks_udp_packet(buffer, bytes_received, chain, src_ip, src_port, data, &udp_data_len);
|
||||
rc = unsocksify_udp_packet(buffer, bytes_received, chain, src_ip, src_port, data, &udp_data_len);
|
||||
if(rc != SUCCESS){
|
||||
PDEBUG("error unSOCKSing the UDP packet\n");
|
||||
return -1;
|
||||
@ -914,8 +932,45 @@ int receive_udp_packet(int sockfd, udp_relay_chain chain, ip_type* src_ip, unsig
|
||||
// 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 encapsulate_udp_packet(udp_relay_chain chain, socks5_addr dst_addr, unsigned short dst_port, void* buffer, size_t* buffer_len){
|
||||
|
||||
PFUNC();
|
||||
|
||||
unsigned int written = 0;
|
||||
unsigned int offset = 0;
|
||||
udp_relay_node * tmp = chain.head;
|
||||
|
||||
while ((tmp->next != NULL) && (written < *buffer_len))
|
||||
{
|
||||
socks5_addr tmpaddr;
|
||||
tmpaddr.atyp = (tmp->next)->bnd_addr.is_v6?ATYP_V6:ATYP_V4;
|
||||
memcpy(tmpaddr.addr.v6, (tmp->next)->bnd_addr.addr.v6, (tmp->next)->bnd_addr.is_v6?16:4);
|
||||
|
||||
written = write_udp_header(tmpaddr, (tmp->next)->bnd_port, 0, buffer+offset, *buffer_len - offset);
|
||||
if (written == -1){
|
||||
PDEBUG("error write_udp_header\n");
|
||||
return -1;
|
||||
}
|
||||
offset += written;
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
written = write_udp_header(dst_addr, dst_port, 0, buffer+offset, *buffer_len-offset);
|
||||
if (written == -1){
|
||||
PDEBUG("error write_udp_header\n");
|
||||
return -1;
|
||||
}
|
||||
offset += written;
|
||||
|
||||
*buffer_len = offset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int socksify_udp_packet(void* udp_data, size_t udp_data_len, udp_relay_chain chain, ip_type dst_ip, unsigned short dst_port, void* buffer, size_t* buffer_len){
|
||||
|
||||
PFUNC();
|
||||
if (chain.head == NULL ){
|
||||
PDEBUG("provided chain is empty\n");
|
||||
return -1;
|
||||
@ -924,119 +979,68 @@ int send_udp_packet(int sockfd, udp_relay_chain chain, ip_type target_ip, unsign
|
||||
char *dns_name = NULL;
|
||||
char hostnamebuf[MSG_LEN_MAX];
|
||||
size_t dns_len = 0;
|
||||
socks5_addr target_addr;
|
||||
socks5_addr dst_addr;
|
||||
// we use ip addresses with 224.* to lookup their dns name in our table, to allow remote DNS resolution
|
||||
// the range 224-255.* is reserved, and it won't go outside (unless the app does some other stuff with
|
||||
// the results returned from gethostbyname et al.)
|
||||
// the hardcoded number 224 can now be changed using the config option remote_dns_subnet to i.e. 127
|
||||
if(!target_ip.is_v6 && proxychains_resolver >= DNSLF_RDNS_START && target_ip.addr.v4.octet[0] == remote_dns_subnet) {
|
||||
target_addr.atyp = ATYP_DOM;
|
||||
dns_len = rdns_get_host_for_ip(target_ip.addr.v4, target_addr.addr.dom.name);
|
||||
if(!dst_ip.is_v6 && proxychains_resolver >= DNSLF_RDNS_START && dst_ip.addr.v4.octet[0] == remote_dns_subnet) {
|
||||
dst_addr.atyp = ATYP_DOM;
|
||||
dns_len = rdns_get_host_for_ip(dst_ip.addr.v4, dst_addr.addr.dom.name);
|
||||
PDEBUG("dnslen: %d\n", dns_len);
|
||||
if(!dns_len) goto err;
|
||||
else dns_name = target_addr.addr.dom.name;
|
||||
target_addr.addr.dom.len = dns_len & 0xFF;
|
||||
PDEBUG("dnslen in struct: %d\n", target_addr.addr.dom.len);
|
||||
if(!dns_len) return -1;
|
||||
else dns_name = dst_addr.addr.dom.name;
|
||||
dst_addr.addr.dom.len = dns_len & 0xFF;
|
||||
PDEBUG("dnslen in struct: %d\n", dst_addr.addr.dom.len);
|
||||
|
||||
} else {
|
||||
if(target_ip.is_v6){
|
||||
target_addr.atyp = ATYP_V6;
|
||||
memcpy(target_addr.addr.v6, target_ip.addr.v6, 16);
|
||||
if(dst_ip.is_v6){
|
||||
dst_addr.atyp = ATYP_V6;
|
||||
memcpy(dst_addr.addr.v6, dst_ip.addr.v6, 16);
|
||||
|
||||
} else {
|
||||
target_addr.atyp = ATYP_V4;
|
||||
memcpy(target_addr.addr.v4.octet, target_ip.addr.v4.octet, 4);
|
||||
dst_addr.atyp = ATYP_V4;
|
||||
memcpy(dst_addr.addr.v4.octet, dst_ip.addr.v4.octet, 4);
|
||||
}
|
||||
}
|
||||
|
||||
PDEBUG("host dns %s\n", dns_name ? dns_name : "<NULL>");
|
||||
|
||||
|
||||
// Write all the UDP headers into the provided buffer
|
||||
int rc;
|
||||
size_t tmp_buffer_len = *buffer_len;
|
||||
rc = encapsulate_udp_packet(chain, dst_addr, dst_port, buffer, &tmp_buffer_len);
|
||||
if(rc != SUCCESS){
|
||||
PDEBUG("error encapsulate_udp_packet()\n");
|
||||
return -1;
|
||||
|
||||
// Allocate a new buffer for the packet data and all the headers
|
||||
unsigned int headers_size = 0;
|
||||
udp_relay_node * tmp = chain.head;
|
||||
int len = 0;
|
||||
while(tmp->next != NULL){
|
||||
|
||||
// switch ((tmp->next)->bnd_addr.atyp)
|
||||
// {
|
||||
// case ATYP_V4:
|
||||
// len = 4;
|
||||
// break;
|
||||
// case ATYP_V6:
|
||||
// len = 6;
|
||||
// break;
|
||||
// case ATYP_DOM:
|
||||
// len = (tmp->next)->bnd_addr.addr.dom.len + 1;
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
|
||||
len = (tmp->next)->bnd_addr.is_v6?16:4;
|
||||
|
||||
headers_size += len + 6;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
switch (target_addr.atyp)
|
||||
{
|
||||
case ATYP_V4:
|
||||
len = 4;
|
||||
break;
|
||||
case ATYP_V6:
|
||||
len = 6;
|
||||
break;
|
||||
case ATYP_DOM:
|
||||
len = target_addr.addr.dom.len + 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
headers_size += len + 6;
|
||||
// Append UDP data in the remaining space of the buffer
|
||||
int min = (udp_data_len>(buffer_len-tmp_buffer_len))?(buffer_len-tmp_buffer_len):udp_data_len;
|
||||
memcpy(buffer + tmp_buffer_len, udp_data, min);
|
||||
|
||||
char * buff = NULL;
|
||||
if (NULL == (buff = (char*)malloc(headers_size+data_len))){
|
||||
PDEBUG("error malloc buffer\n");
|
||||
*buffer_len = tmp_buffer_len + min;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
PFUNC();
|
||||
char send_buffer[65535];
|
||||
size_t send_buffer_len = sizeof(send_buffer);
|
||||
int rc;
|
||||
|
||||
rc = socksify_udp_packet(data, data_len, chain, target_ip, target_port,send_buffer, &send_buffer_len);
|
||||
if(rc != SUCCESS){
|
||||
PDEBUG("error socksify_udp_packet()\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Append each header to the buffer
|
||||
|
||||
unsigned int written = 0;
|
||||
unsigned int offset = 0;
|
||||
|
||||
tmp = chain.head;
|
||||
while (tmp->next != NULL)
|
||||
{
|
||||
|
||||
socks5_addr tmpaddr;
|
||||
tmpaddr.atyp = (tmp->next)->bnd_addr.is_v6?ATYP_V6:ATYP_V4;
|
||||
memcpy(tmpaddr.addr.v6, (tmp->next)->bnd_addr.addr.v6, (tmp->next)->bnd_addr.is_v6?16:4);
|
||||
|
||||
written = write_udp_header(tmpaddr, (tmp->next)->bnd_port, 0, buff+offset, headers_size + data_len - offset);
|
||||
if (written == -1){
|
||||
PDEBUG("error write_udp_header\n");
|
||||
goto err;
|
||||
}
|
||||
offset += written;
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
written = write_udp_header(target_addr, target_port, 0, buff + offset, headers_size + data_len - offset);
|
||||
if (written == -1){
|
||||
PDEBUG("error write_udp_header\n");
|
||||
goto err;
|
||||
}
|
||||
offset += written;
|
||||
|
||||
// Append data to the buffer
|
||||
memcpy(buff + offset, data, data_len);
|
||||
|
||||
// Send the packet
|
||||
// FIXME: should write_n_bytes be used here instead ?
|
||||
|
||||
@ -1059,21 +1063,176 @@ int send_udp_packet(int sockfd, udp_relay_chain chain, ip_type target_ip, unsign
|
||||
|
||||
int sent = 0;
|
||||
|
||||
sent = true_sendto(sockfd, buff, offset+data_len, 0, (struct sockaddr *) (v6?(void*)&addr6:(void*)&addr), v6?sizeof(addr6):sizeof(addr) );
|
||||
if (sent != offset+data_len){
|
||||
sent = true_sendto(sockfd, send_buffer, send_buffer_len, 0, (struct sockaddr *) (v6?(void*)&addr6:(void*)&addr), v6?sizeof(addr6):sizeof(addr) );
|
||||
if (sent != send_buffer_len){
|
||||
PDEBUG("true_sendto error\n");
|
||||
goto err;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
|
||||
err:
|
||||
free(buff);
|
||||
return -1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
||||
// if (chain.head == NULL ){
|
||||
// PDEBUG("provided chain is empty\n");
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
// char *dns_name = NULL;
|
||||
// char hostnamebuf[MSG_LEN_MAX];
|
||||
// size_t dns_len = 0;
|
||||
// socks5_addr target_addr;
|
||||
// // we use ip addresses with 224.* to lookup their dns name in our table, to allow remote DNS resolution
|
||||
// // the range 224-255.* is reserved, and it won't go outside (unless the app does some other stuff with
|
||||
// // the results returned from gethostbyname et al.)
|
||||
// // the hardcoded number 224 can now be changed using the config option remote_dns_subnet to i.e. 127
|
||||
// if(!target_ip.is_v6 && proxychains_resolver >= DNSLF_RDNS_START && target_ip.addr.v4.octet[0] == remote_dns_subnet) {
|
||||
// target_addr.atyp = ATYP_DOM;
|
||||
// dns_len = rdns_get_host_for_ip(target_ip.addr.v4, target_addr.addr.dom.name);
|
||||
// PDEBUG("dnslen: %d\n", dns_len);
|
||||
// if(!dns_len) goto err;
|
||||
// else dns_name = target_addr.addr.dom.name;
|
||||
// target_addr.addr.dom.len = dns_len & 0xFF;
|
||||
// PDEBUG("dnslen in struct: %d\n", target_addr.addr.dom.len);
|
||||
|
||||
// } else {
|
||||
// if(target_ip.is_v6){
|
||||
// target_addr.atyp = ATYP_V6;
|
||||
// memcpy(target_addr.addr.v6, target_ip.addr.v6, 16);
|
||||
|
||||
// } else {
|
||||
// target_addr.atyp = ATYP_V4;
|
||||
// memcpy(target_addr.addr.v4.octet, target_ip.addr.v4.octet, 4);
|
||||
// }
|
||||
// }
|
||||
|
||||
// PDEBUG("host dns %s\n", dns_name ? dns_name : "<NULL>");
|
||||
|
||||
|
||||
|
||||
// // Allocate a new buffer for the packet data and all the headers
|
||||
// unsigned int headers_size = 0;
|
||||
// udp_relay_node * tmp = chain.head;
|
||||
// int len = 0;
|
||||
// while(tmp->next != NULL){
|
||||
|
||||
// // switch ((tmp->next)->bnd_addr.atyp)
|
||||
// // {
|
||||
// // case ATYP_V4:
|
||||
// // len = 4;
|
||||
// // break;
|
||||
// // case ATYP_V6:
|
||||
// // len = 6;
|
||||
// // break;
|
||||
// // case ATYP_DOM:
|
||||
// // len = (tmp->next)->bnd_addr.addr.dom.len + 1;
|
||||
// // break;
|
||||
// // default:
|
||||
// // break;
|
||||
// // }
|
||||
|
||||
// len = (tmp->next)->bnd_addr.is_v6?16:4;
|
||||
|
||||
// headers_size += len + 6;
|
||||
// tmp = tmp->next;
|
||||
// }
|
||||
|
||||
// switch (target_addr.atyp)
|
||||
// {
|
||||
// case ATYP_V4:
|
||||
// len = 4;
|
||||
// break;
|
||||
// case ATYP_V6:
|
||||
// len = 6;
|
||||
// break;
|
||||
// case ATYP_DOM:
|
||||
// len = target_addr.addr.dom.len + 1;
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
|
||||
// headers_size += len + 6;
|
||||
|
||||
// char * buff = NULL;
|
||||
// if (NULL == (buff = (char*)malloc(headers_size+data_len))){
|
||||
// PDEBUG("error malloc buffer\n");
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
|
||||
// // Append each header to the buffer
|
||||
|
||||
// unsigned int written = 0;
|
||||
// unsigned int offset = 0;
|
||||
|
||||
// tmp = chain.head;
|
||||
// while (tmp->next != NULL)
|
||||
// {
|
||||
|
||||
// socks5_addr tmpaddr;
|
||||
// tmpaddr.atyp = (tmp->next)->bnd_addr.is_v6?ATYP_V6:ATYP_V4;
|
||||
// memcpy(tmpaddr.addr.v6, (tmp->next)->bnd_addr.addr.v6, (tmp->next)->bnd_addr.is_v6?16:4);
|
||||
|
||||
// written = write_udp_header(tmpaddr, (tmp->next)->bnd_port, 0, buff+offset, headers_size + data_len - offset);
|
||||
// if (written == -1){
|
||||
// PDEBUG("error write_udp_header\n");
|
||||
// goto err;
|
||||
// }
|
||||
// offset += written;
|
||||
|
||||
// tmp = tmp->next;
|
||||
// }
|
||||
|
||||
// written = write_udp_header(target_addr, target_port, 0, buff + offset, headers_size + data_len - offset);
|
||||
// if (written == -1){
|
||||
// PDEBUG("error write_udp_header\n");
|
||||
// goto err;
|
||||
// }
|
||||
// offset += written;
|
||||
|
||||
// // Append data to the buffer
|
||||
// memcpy(buff + offset, data, data_len);
|
||||
|
||||
// // Send the packet
|
||||
// // FIXME: should write_n_bytes be used here instead ?
|
||||
|
||||
// // if(chain.head->bnd_addr.atyp == ATYP_DOM){
|
||||
// // PDEBUG("BND_ADDR of type DOMAINE (0x03) not supported yet\n");
|
||||
// // goto err;
|
||||
// // }
|
||||
// int v6 = chain.head->bnd_addr.is_v6 == ATYP_V6;
|
||||
|
||||
// struct sockaddr_in addr = {
|
||||
// .sin_family = AF_INET,
|
||||
// .sin_port = chain.head->bnd_port,
|
||||
// .sin_addr.s_addr = (in_addr_t) chain.head->bnd_addr.addr.v4.as_int,
|
||||
// };
|
||||
// struct sockaddr_in6 addr6 = {
|
||||
// .sin6_family = AF_INET6,
|
||||
// .sin6_port = chain.head->bnd_port,
|
||||
// };
|
||||
// if(v6) memcpy(&addr6.sin6_addr.s6_addr, chain.head->bnd_addr.addr.v6, 16);
|
||||
|
||||
// int sent = 0;
|
||||
|
||||
// sent = true_sendto(sockfd, buff, offset+data_len, 0, (struct sockaddr *) (v6?(void*)&addr6:(void*)&addr), v6?sizeof(addr6):sizeof(addr) );
|
||||
// if (sent != offset+data_len){
|
||||
// PDEBUG("true_sendto error\n");
|
||||
// goto err;
|
||||
// }
|
||||
|
||||
// return SUCCESS;
|
||||
|
||||
// err:
|
||||
// free(buff);
|
||||
// return -1;
|
||||
|
||||
|
||||
// }
|
||||
|
||||
|
||||
#define TP " ... "
|
||||
#define DT "Dynamic chain"
|
||||
|
@ -1021,6 +1021,7 @@ HOOKFUNC(ssize_t, sendto, int sockfd, const void *buf, size_t len, int flags,
|
||||
DUMP_RELAY_CHAINS_LIST(relay_chains);
|
||||
|
||||
memcpy(dest_ip.addr.v6, v6 ? (void*)p_addr_in6 : (void*)p_addr_in, v6?16:4);
|
||||
//TODO: is it better to do 'return send_udp_packet' ?
|
||||
if (SUCCESS != send_udp_packet(sockfd, *relay_chain, dest_ip, htons(port),0, buf, len)){
|
||||
PDEBUG("could not send udp packet\n");
|
||||
errno = ECONNREFUSED;
|
||||
@ -1031,10 +1032,188 @@ HOOKFUNC(ssize_t, sendto, int sockfd, const void *buf, size_t len, int flags,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// HOOKFUNC(ssize_t, sendmsg, int sockfd, const struct msghdr *msg, int flags){
|
||||
// //TODO hugoc
|
||||
// return 0;
|
||||
// }
|
||||
HOOKFUNC(ssize_t, sendmsg, int sockfd, const struct msghdr *msg, int flags){
|
||||
INIT();
|
||||
PFUNC();
|
||||
|
||||
//TODO : do we keep this FASTOPEN code from sendto() ?
|
||||
// if (flags & MSG_FASTOPEN) {
|
||||
// if (!connect(sockfd, dest_addr, addrlen) && errno != EINPROGRESS) {
|
||||
// return -1;
|
||||
// }
|
||||
// dest_addr = NULL;
|
||||
// addrlen = 0;
|
||||
// flags &= ~MSG_FASTOPEN;
|
||||
|
||||
// return true_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
|
||||
// }
|
||||
|
||||
//TODO hugoc: case of SOCK_DGRAM with AF_INET or AF_INET6
|
||||
struct sockaddr* dest_addr;
|
||||
dest_addr = msg->msg_name;
|
||||
socklen_t addrlen = msg->msg_namelen;
|
||||
|
||||
DEBUGDECL(char str[256]);
|
||||
int socktype = 0, ret = 0;
|
||||
socklen_t optlen = 0;
|
||||
optlen = sizeof(socktype);
|
||||
sa_family_t fam = SOCKFAMILY(*dest_addr);
|
||||
getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &socktype, &optlen);
|
||||
if(!((fam == AF_INET || fam == AF_INET6) && socktype == SOCK_DGRAM)){
|
||||
return true_sendmsg(sockfd, msg, flags);
|
||||
}
|
||||
|
||||
PDEBUG("before send dump : ");
|
||||
DUMP_BUFFER(msg->msg_name, msg->msg_namelen);
|
||||
|
||||
ip_type dest_ip;
|
||||
struct in_addr *p_addr_in;
|
||||
struct in6_addr *p_addr_in6;
|
||||
dnat_arg *dnat = NULL;
|
||||
size_t i;
|
||||
int remote_dns_connect = 0;
|
||||
unsigned short port;
|
||||
int v6 = dest_ip.is_v6 = fam == AF_INET6;
|
||||
|
||||
p_addr_in = &((struct sockaddr_in *) dest_addr)->sin_addr;
|
||||
p_addr_in6 = &((struct
|
||||
sockaddr_in6 *) dest_addr)->sin6_addr;
|
||||
port = !v6 ? ntohs(((struct sockaddr_in *) dest_addr)->sin_port)
|
||||
: ntohs(((struct sockaddr_in6 *) dest_addr)->sin6_port);
|
||||
struct in_addr v4inv6;
|
||||
if(v6 && is_v4inv6(p_addr_in6)) {
|
||||
memcpy(&v4inv6.s_addr, &p_addr_in6->s6_addr[12], 4);
|
||||
v6 = dest_ip.is_v6 = 0;
|
||||
p_addr_in = &v4inv6;
|
||||
}
|
||||
if(!v6 && !memcmp(p_addr_in, "\0\0\0\0", 4)) {
|
||||
errno = ECONNREFUSED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
PDEBUG("target: %s\n", inet_ntop(v6 ? AF_INET6 : AF_INET, v6 ? (void*)p_addr_in6 : (void*)p_addr_in, str, sizeof(str)));
|
||||
PDEBUG("port: %d\n", port);
|
||||
PDEBUG("client socket: %d\n", sockfd);
|
||||
|
||||
// check if connect called from proxydns
|
||||
remote_dns_connect = !v6 && (ntohl(p_addr_in->s_addr) >> 24 == remote_dns_subnet);
|
||||
|
||||
// more specific first
|
||||
if (!v6) for(i = 0; i < num_dnats && !remote_dns_connect && !dnat; i++)
|
||||
if(dnats[i].orig_dst.s_addr == p_addr_in->s_addr)
|
||||
if(dnats[i].orig_port && (dnats[i].orig_port == port))
|
||||
dnat = &dnats[i];
|
||||
|
||||
if (!v6) for(i = 0; i < num_dnats && !remote_dns_connect && !dnat; i++)
|
||||
if(dnats[i].orig_dst.s_addr == p_addr_in->s_addr)
|
||||
if(!dnats[i].orig_port)
|
||||
dnat = &dnats[i];
|
||||
|
||||
if (dnat) {
|
||||
p_addr_in = &dnat->new_dst;
|
||||
if (dnat->new_port)
|
||||
port = dnat->new_port;
|
||||
}
|
||||
|
||||
for(i = 0; i < num_localnet_addr && !remote_dns_connect; i++) {
|
||||
if (localnet_addr[i].port && localnet_addr[i].port != port)
|
||||
continue;
|
||||
if (localnet_addr[i].family != (v6 ? AF_INET6 : AF_INET))
|
||||
continue;
|
||||
if (v6) {
|
||||
size_t prefix_bytes = localnet_addr[i].in6_prefix / CHAR_BIT;
|
||||
size_t prefix_bits = localnet_addr[i].in6_prefix % CHAR_BIT;
|
||||
if (prefix_bytes && memcmp(p_addr_in6->s6_addr, localnet_addr[i].in6_addr.s6_addr, prefix_bytes) != 0)
|
||||
continue;
|
||||
if (prefix_bits && (p_addr_in6->s6_addr[prefix_bytes] ^ localnet_addr[i].in6_addr.s6_addr[prefix_bytes]) >> (CHAR_BIT - prefix_bits))
|
||||
continue;
|
||||
} else {
|
||||
if((p_addr_in->s_addr ^ localnet_addr[i].in_addr.s_addr) & localnet_addr[i].in_mask.s_addr)
|
||||
continue;
|
||||
}
|
||||
PDEBUG("accessing localnet using true_sendmsg\n");
|
||||
return true_sendmsg(sockfd, msg, flags);
|
||||
}
|
||||
|
||||
// Check if a chain of UDP relay is already opened for this socket
|
||||
udp_relay_chain* relay_chain = get_relay_chain(relay_chains, sockfd);
|
||||
if(relay_chain == NULL){
|
||||
// No chain is opened for this socket, open one
|
||||
PDEBUG("opening new chain of relays for %d\n", sockfd);
|
||||
if(NULL == (relay_chain = open_relay_chain(proxychains_pd, proxychains_proxy_count, proxychains_ct, proxychains_max_chain))){
|
||||
PDEBUG("could not open a chain of relay\n");
|
||||
errno = ECONNREFUSED;
|
||||
return -1;
|
||||
}
|
||||
relay_chain->sockfd = sockfd;
|
||||
add_relay_chain(&relay_chains, relay_chain);
|
||||
}
|
||||
DUMP_RELAY_CHAINS_LIST(relay_chains);
|
||||
|
||||
memcpy(dest_ip.addr.v6, v6 ? (void*)p_addr_in6 : (void*)p_addr_in, v6?16:4);
|
||||
|
||||
|
||||
// Allocate buffer for header creation
|
||||
char send_buffer[65535]; //TODO maybe we can do better about size ?
|
||||
size_t send_buffer_len = sizeof(send_buffer);
|
||||
|
||||
//Move iovec udp data contained in msg to one buffer
|
||||
char udp_data[65535];
|
||||
size_t udp_data_len = sizeof(udp_data);
|
||||
udp_data_len = write_iov_to_buf(udp_data, udp_data_len, msg->msg_iov, msg->msg_iovlen);
|
||||
|
||||
// Exec socksify_udp_packet
|
||||
int rc;
|
||||
rc = socksify_udp_packet(udp_data, udp_data_len, *relay_chain, dest_ip, htons(port),send_buffer, &send_buffer_len);
|
||||
if(rc != SUCCESS){
|
||||
PDEBUG("error socksify_udp_packet()\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// send with true_sendmsg()
|
||||
//prepare our msg
|
||||
struct iovec iov[1];
|
||||
iov[0].iov_base = send_buffer;
|
||||
iov[0].iov_len = send_buffer_len;
|
||||
|
||||
|
||||
struct msghdr tmp_msg;
|
||||
tmp_msg.msg_control = msg->msg_control;
|
||||
tmp_msg.msg_controllen = msg->msg_controllen;
|
||||
tmp_msg.msg_flags = msg->msg_flags;
|
||||
tmp_msg.msg_iov = iov;
|
||||
tmp_msg.msg_iovlen = 1;
|
||||
|
||||
v6 = relay_chain->head->bnd_addr.is_v6 == ATYP_V6;
|
||||
struct sockaddr_in addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = relay_chain->head->bnd_port,
|
||||
.sin_addr.s_addr = (in_addr_t) relay_chain->head->bnd_addr.addr.v4.as_int,
|
||||
};
|
||||
struct sockaddr_in6 addr6 = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_port = relay_chain->head->bnd_port,
|
||||
};
|
||||
if(v6) memcpy(&addr6.sin6_addr.s6_addr, relay_chain->head->bnd_addr.addr.v6, 16);
|
||||
|
||||
|
||||
|
||||
tmp_msg.msg_name = (struct sockaddr*)(v6?(void*)&addr6:(void*)&addr);
|
||||
tmp_msg.msg_namelen = v6?sizeof(addr6):sizeof(addr) ;
|
||||
|
||||
|
||||
//send it
|
||||
|
||||
int sent = 0;
|
||||
sent = true_sendmsg(sockfd, &tmp_msg, flags);
|
||||
if(-1 == sent){
|
||||
PDEBUG("error true_sendmsg\n");
|
||||
return -1;
|
||||
}
|
||||
PDEBUG("Successfully sent UDP packet with true_sendmsg()\n");
|
||||
return sent;
|
||||
}
|
||||
|
||||
HOOKFUNC(ssize_t, recvmsg, int sockfd, struct msghdr *msg, int flags){
|
||||
|
||||
@ -1100,7 +1279,7 @@ HOOKFUNC(ssize_t, recvmsg, int sockfd, struct msghdr *msg, int flags){
|
||||
PDEBUG("exec true_recvmsg\n");
|
||||
bytes_received = true_recvmsg(sockfd, &tmp_msg, flags);
|
||||
if(-1 == bytes_received){
|
||||
PDEBUG("true_recvmsg returned -1\n");
|
||||
PDEBUG("true_recvmsg returned -1, errno: %d, %s\n", errno,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1112,8 +1291,9 @@ HOOKFUNC(ssize_t, recvmsg, int sockfd, struct msghdr *msg, int 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))){
|
||||
DUMP_BUFFER(tmp_msg.msg_name, tmp_msg.msg_namelen);
|
||||
DUMP_BUFFER(relay_chain->head->bnd_addr.addr.v4.octet, 4);
|
||||
if(!is_from_chain_head(*relay_chain, *(struct sockaddr *)(tmp_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);
|
||||
@ -1137,7 +1317,7 @@ HOOKFUNC(ssize_t, recvmsg, int sockfd, struct msghdr *msg, int flags){
|
||||
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);
|
||||
rc = unsocksify_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;
|
||||
@ -1178,7 +1358,7 @@ HOOKFUNC(ssize_t, recvmsg, int sockfd, struct msghdr *msg, int flags){
|
||||
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);
|
||||
msg->msg_namelen = sizeof(struct sockaddr_in);
|
||||
}
|
||||
else if(src_ip.is_v6){
|
||||
PDEBUG("src_ip is true v6\n");
|
||||
@ -1190,7 +1370,7 @@ HOOKFUNC(ssize_t, recvmsg, int sockfd, struct msghdr *msg, int flags){
|
||||
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);
|
||||
msg->msg_namelen = sizeof(struct sockaddr_in6);
|
||||
}else {
|
||||
if(msg->msg_namelen < sizeof(struct sockaddr_in)){
|
||||
PDEBUG("addrlen too short for ipv4\n");
|
||||
@ -1199,9 +1379,11 @@ HOOKFUNC(ssize_t, recvmsg, int sockfd, struct msghdr *msg, int flags){
|
||||
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);
|
||||
msg->msg_namelen = sizeof(struct sockaddr_in);
|
||||
}
|
||||
}
|
||||
PDEBUG("after recv dump : ");
|
||||
DUMP_BUFFER(msg->msg_name, msg->msg_namelen);
|
||||
|
||||
|
||||
return udp_data_len;
|
||||
@ -1382,7 +1564,7 @@ static void setup_hooks(void) {
|
||||
SETUP_SYM(sendto);
|
||||
SETUP_SYM(recvfrom);
|
||||
SETUP_SYM(recvmsg);
|
||||
//SETUP_SYM(sendmsg);
|
||||
SETUP_SYM(sendmsg);
|
||||
SETUP_SYM(recv);
|
||||
SETUP_SYM(gethostbyname);
|
||||
SETUP_SYM(getaddrinfo);
|
||||
|
Loading…
Reference in New Issue
Block a user