mirror of
https://github.com/rofl0r/proxychains-ng
synced 2025-01-08 06:02:51 +08:00
hook connect and getpeername
This commit is contained in:
parent
95036aac7b
commit
23c9654cf8
52
src/core.c
52
src/core.c
@ -1655,7 +1655,12 @@ int add_node_to_chain(proxy_data * pd, udp_relay_chain * chain){
|
||||
return -1;
|
||||
}
|
||||
|
||||
int free_relay_chain_nodes(udp_relay_chain chain){
|
||||
int free_relay_chain(udp_relay_chain chain){
|
||||
if(NULL != chain.connected_peer_addr){
|
||||
free(chain.connected_peer_addr);
|
||||
chain.connected_peer_addr = NULL;
|
||||
}
|
||||
|
||||
if(chain.head == NULL){
|
||||
return SUCCESS;
|
||||
}
|
||||
@ -1687,6 +1692,8 @@ udp_relay_chain * open_relay_chain(proxy_data *pd, unsigned int proxy_count, cha
|
||||
|
||||
new_chain->head = NULL;
|
||||
new_chain->sockfd = -1;
|
||||
new_chain->connected_peer_addr = NULL;
|
||||
new_chain->connected_peer_addr_len = -1;
|
||||
|
||||
|
||||
unsigned int alive_count = 0;
|
||||
@ -1730,12 +1737,53 @@ udp_relay_chain * open_relay_chain(proxy_data *pd, unsigned int proxy_count, cha
|
||||
error:
|
||||
PDEBUG("error\n");
|
||||
release_all(pd, proxy_count);
|
||||
free_relay_chain_nodes(*new_chain);
|
||||
free_relay_chain(*new_chain);
|
||||
free(new_chain);
|
||||
errno = ETIMEDOUT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Checks the address family of addr, allocates a matching structure and keeps a pointer to it in the chain structure to store the address of the connected peer
|
||||
void set_connected_peer_addr(udp_relay_chain* chain, struct sockaddr* addr, socklen_t addrlen){
|
||||
|
||||
sa_family_t fam = ((struct sockaddr_in*)addr)->sin_family;
|
||||
int v6 = fam == AF_INET6;
|
||||
|
||||
|
||||
|
||||
if(v6){
|
||||
struct sockaddr_in6* old_addr6 = (struct sockaddr_in6*)addr;
|
||||
struct sockaddr_in6* new_addr6 = NULL;
|
||||
if(NULL == (new_addr6 = (struct sockaddr_in6*)malloc(sizeof(struct sockaddr_in6)))){
|
||||
PDEBUG("error malloc\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_addr6->sin6_family = old_addr6->sin6_family;
|
||||
new_addr6->sin6_port = old_addr6->sin6_port;
|
||||
memcpy(new_addr6->sin6_addr.s6_addr, old_addr6->sin6_addr.s6_addr, 16);
|
||||
|
||||
chain->connected_peer_addr = (struct sockaddr*)new_addr6;
|
||||
chain->connected_peer_addr_len = sizeof(struct sockaddr_in6);
|
||||
|
||||
} else{
|
||||
struct sockaddr_in* old_addr = (struct sockaddr_in*)addr;
|
||||
struct sockaddr_in* new_addr = NULL;
|
||||
if(NULL == (new_addr = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in)))){
|
||||
PDEBUG("error malloc\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_addr->sin_family = old_addr->sin_family;
|
||||
new_addr->sin_port = old_addr->sin_port;
|
||||
new_addr->sin_addr.s_addr = old_addr->sin_addr.s_addr;
|
||||
|
||||
chain->connected_peer_addr = (struct sockaddr*)new_addr;
|
||||
chain->connected_peer_addr_len = sizeof(struct sockaddr_in);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void add_relay_chain(udp_relay_chain_list* chains_list, udp_relay_chain* new_chain){
|
||||
|
||||
|
@ -131,7 +131,9 @@ typedef struct s_udp_relay_node {
|
||||
/* A structure to hold the chain of udp relay servers assiociated with a client socket */
|
||||
typedef struct s_udp_relay_chain {
|
||||
int sockfd; // the client socket for which the chain of relays has been set up
|
||||
udp_relay_node * head; // head of the linked list of udp_relay_node
|
||||
udp_relay_node * head; // head of the linked list of udp_relay_node
|
||||
struct sockaddr* connected_peer_addr; // used to store the address of the peer which the sockfd is connected to (in case connect() is used on the socket)
|
||||
socklen_t connected_peer_addr_len;
|
||||
struct s_udp_relay_chain * prev;
|
||||
struct s_udp_relay_chain * next;
|
||||
} udp_relay_chain;
|
||||
@ -173,6 +175,7 @@ typedef ssize_t (*recvfrom_t) (int sockfd, void *buf, size_t len, int flags,
|
||||
typedef ssize_t (*sendmsg_t) (int sockfd, const struct msghdr *msg, int flags);
|
||||
typedef int (*sendmmsg_t) (int sockfd, struct mmsghdr* msgvec, unsigned int vlen, int flags);
|
||||
typedef ssize_t (*recvmsg_t) (int sockfd, struct msghdr *msg, int flags);
|
||||
typedef int (*getpeername_t) (int sockfd, struct sockaddr *restrict addr, socklen_t *restrict addrlen);
|
||||
|
||||
|
||||
extern connect_t true_connect;
|
||||
@ -188,6 +191,7 @@ extern send_t true_send;
|
||||
extern sendmsg_t true_sendmsg;
|
||||
extern sendmmsg_t true_sendmmsg;
|
||||
extern recvmsg_t true_recvmsg;
|
||||
extern getpeername_t true_getpeername;
|
||||
|
||||
struct gethostbyname_data {
|
||||
struct hostent hostent_space;
|
||||
@ -210,7 +214,7 @@ static int udp_associate(int sock, ip_type * dst_addr, unsigned short dst_port,
|
||||
udp_relay_chain* get_relay_chain(udp_relay_chain_list chains_list, int sockfd);
|
||||
void del_relay_chain(udp_relay_chain_list* chains_list, udp_relay_chain* chain);
|
||||
void add_relay_chain(udp_relay_chain_list* chains_list, udp_relay_chain* new_chain);
|
||||
int free_relay_chain_nodes(udp_relay_chain chain);
|
||||
int free_relay_chain(udp_relay_chain chain);
|
||||
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 flags);
|
||||
int receive_udp_packet(int sockfd, udp_relay_chain chain, ip_type* src_addr, unsigned short* src_port, char* data, unsigned int data_len );
|
||||
@ -221,6 +225,7 @@ int is_from_chain_head(udp_relay_chain chain, struct sockaddr src_addr);
|
||||
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);
|
||||
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);
|
||||
int encapsulate_udp_packet(udp_relay_chain chain, socks5_addr dst_addr, unsigned short dst_port, void* buffer, size_t* buffer_len);
|
||||
void set_connected_peer_addr(udp_relay_chain* chain, struct sockaddr* addr, socklen_t addrlen);
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -70,6 +70,7 @@ recvfrom_t true_recvfrom;
|
||||
sendmsg_t true_sendmsg;
|
||||
recvmsg_t true_recvmsg;
|
||||
sendmmsg_t true_sendmmsg;
|
||||
getpeername_t true_getpeername;
|
||||
|
||||
int tcp_read_time_out;
|
||||
int tcp_connect_time_out;
|
||||
@ -600,13 +601,13 @@ HOOKFUNC(int, close, int fd) {
|
||||
}
|
||||
|
||||
/***** UDP STUFF *******/
|
||||
PDEBUG("checking if a relay chain is opened for fd %d\n", fd);
|
||||
//PDEBUG("checking if a relay chain is opened for fd %d\n", fd);
|
||||
udp_relay_chain* chain = NULL;
|
||||
|
||||
chain = get_relay_chain(relay_chains, fd);
|
||||
if(NULL != chain){
|
||||
PDEBUG("fd %d corresponds to chain %x, closing it\n", fd, chain);
|
||||
free_relay_chain_nodes(*chain);
|
||||
free_relay_chain(*chain);
|
||||
del_relay_chain(&relay_chains, chain);
|
||||
}
|
||||
|
||||
@ -692,6 +693,68 @@ HOOKFUNC(int, close_range, unsigned first, unsigned last, int flags) {
|
||||
return res;
|
||||
}
|
||||
|
||||
HOOKFUNC(int, getpeername, int sockfd, struct sockaddr *restrict addr, socklen_t *restrict addrlen){
|
||||
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_getpeername\n", sockfd);
|
||||
return true_getpeername(sockfd, addr, addrlen);
|
||||
}
|
||||
PDEBUG("sockfd %d is a SOCK_DGRAM socket\n", sockfd);
|
||||
|
||||
struct sockaddr sock_addr;
|
||||
socklen_t sock_addr_len = sizeof(sock_addr);
|
||||
if(SUCCESS != getsockname(sockfd, &sock_addr, &sock_addr_len )){
|
||||
PDEBUG("error getsockname, errno=%d. Returning to true_getpeernam()\n", errno);
|
||||
return true_getpeername(sockfd, addr, addrlen);
|
||||
}
|
||||
sa_family_t fam = SOCKFAMILY(sock_addr);
|
||||
if(!(fam == AF_INET || fam == AF_INET6)){
|
||||
PDEBUG("sockfd %d address familiy is not a AF_INET or AF_INET6, returning to true_getpeername\n", sockfd);
|
||||
return true_getpeername(sockfd, addr, addrlen);
|
||||
}
|
||||
|
||||
PDEBUG("sockfd %d's address family is AF_INET or AF_INET6\n", sockfd);
|
||||
|
||||
|
||||
/* BEGIN UDP STUFF*/
|
||||
|
||||
|
||||
// Check if a relay chain exists for the socket
|
||||
udp_relay_chain* relay_chain = get_relay_chain(relay_chains, sockfd);
|
||||
if(relay_chain == NULL){
|
||||
PDEBUG("no relay chain exists for socket %d, returning true_getpeername()\n", sockfd);
|
||||
return true_getpeername(sockfd, addr, addrlen);
|
||||
}
|
||||
|
||||
// Check if a connected peer address is stored in the relay chain structure
|
||||
if(relay_chain->connected_peer_addr == NULL){
|
||||
PDEBUG("no connected peer address is stored for socket %d, returning true_getpeername()\n", sockfd);
|
||||
return true_getpeername(sockfd, addr, addrlen);
|
||||
}
|
||||
|
||||
// If a connected peer address is stored in the relay chain structure, return it
|
||||
|
||||
socklen_t provided_addr_len = *addrlen;
|
||||
|
||||
|
||||
size_t min = (provided_addr_len<relay_chain->connected_peer_addr_len)?provided_addr_len:relay_chain->connected_peer_addr_len;
|
||||
memcpy(addr, relay_chain->connected_peer_addr, min);
|
||||
|
||||
*addrlen = min;
|
||||
|
||||
return SUCCESS;
|
||||
|
||||
/* END UDP STUFF */
|
||||
|
||||
}
|
||||
|
||||
HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len) {
|
||||
INIT();
|
||||
PFUNC();
|
||||
@ -710,6 +773,51 @@ HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len)
|
||||
optlen = sizeof(socktype);
|
||||
sa_family_t fam = SOCKFAMILY(*addr);
|
||||
getsockopt(sock, SOL_SOCKET, SO_TYPE, &socktype, &optlen);
|
||||
|
||||
/* BEGIN UDP STUFF*/
|
||||
if(((fam == AF_INET || fam == AF_INET6) && socktype == SOCK_DGRAM)){
|
||||
PDEBUG("connect() on an UDP socket\n");
|
||||
|
||||
// Check if a relay chain is already opened for the socket fd, otherwise open it
|
||||
udp_relay_chain* relay_chain = get_relay_chain(relay_chains, sock);
|
||||
if(relay_chain == NULL){
|
||||
// No chain is opened for this socket, open one
|
||||
PDEBUG("opening new chain of relays for %d\n", sock);
|
||||
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 = sock;
|
||||
add_relay_chain(&relay_chains, relay_chain);
|
||||
}
|
||||
DUMP_RELAY_CHAINS_LIST(relay_chains);
|
||||
|
||||
|
||||
// Store the peer address in the relay chain structure, in order to be able to retrieve it in subsequent calls to send(), sendmsg(), ...
|
||||
set_connected_peer_addr(relay_chain, addr, len);
|
||||
|
||||
|
||||
// Connect the socket to the relay chain's head, so that subsequent calls to poll(), recv(), recvfrom(), ... can return data comming from this peer
|
||||
|
||||
int 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);
|
||||
|
||||
return true_connect(sock, (struct sockaddr *) (v6?(void*)&addr6:(void*)&addr), v6?sizeof(addr6):sizeof(addr) );
|
||||
}
|
||||
|
||||
/* END UDP STUFF*/
|
||||
|
||||
if(!((fam == AF_INET || fam == AF_INET6) && socktype == SOCK_STREAM))
|
||||
return true_connect(sock, addr, len);
|
||||
|
||||
@ -1859,6 +1967,7 @@ HOOKFUNC(ssize_t, send, int sockfd, const void *buf, size_t len, int flags){
|
||||
|
||||
static void setup_hooks(void) {
|
||||
SETUP_SYM(connect);
|
||||
SETUP_SYM(getpeername);
|
||||
SETUP_SYM(send);
|
||||
SETUP_SYM(sendto);
|
||||
SETUP_SYM(recvfrom);
|
||||
|
Loading…
Reference in New Issue
Block a user