proxychains是怎麼工作的

2021-09-12 17:52:12 字數 3878 閱讀 6625

proxychains可以讓命令通過指定的proxy訪問網路。

例如:

wget www.google.com
由於防火牆的原因,直接訪問不通。

如果已經有乙個**服務(socks5:配置proxychains之後:

proxychains wget www.google.com
可以正常訪問了

動態鏈結與ld_preload

靜態鏈結與動態鏈結具體的可以看這裡。簡單理解就是:

動態鏈結就是程式的依賴在執行的時候才載入,依賴通常都是以so庫提供,程式在執行時動態的找到so庫並載入。

ld_preload環境變數允許你定義在程式執行前優先載入的動態鏈結庫。

比如,程式main依賴a.so庫,a.so中包含有method1()方法。此時,我們自己寫乙個b.so,也包函式簽名完全一樣的method1()方法,然後我們指定ld_preload=b.so,這時main程式在執行時呼叫的method1()就是b.so中的method1()

linux環境下的程式在訪問網路的時候最終都會用到底層的libc.so提供的網路函式,如,tcp協議一定會用到connect函式來建立tcp連線。如果把connect函式重寫並編譯成whatever.so檔案,再把ld_preload設定成whatever.so,這樣我們的程式在建立tcp連線的時候就會調到我們重寫的connect函式。

dlsym函式

dlsym(dynamic library symbol)
通過dlsym可以拿到libc中的真實的connect函式的位址,然後用真實的connect函式與**伺服器建立連線,把資料報傳送到**伺服器。

dup2函式實現重定向

深入理解dup和dup2函式可以看這裡

簡單來說,用dup2可以實現把檔案描述符a重定向到檔案描述符b。也就是說,所有對a有寫入,最終都會寫入到b。

好了,梳理一下流程

簡易的proxychains實現

libproxy.c

#undef _gnu_source

#define _gnu_source

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*#include */

#define satosin(x) ((struct sockaddr_in *) &(x))

#define sockfamily(x) (satosin(x)->sin_family)

#define buff_size 8*1024 // used to read responses from proxies.

#define dns_name_size 100 // used to read responses from proxies.

static int poll_retry(struct pollfd *fds, nfds_t nfsd, int timeout)

while(ret == -1 && errno == eintr && time_remain > 0);

//if (ret == -1)

//printf("return %d %d %s\n", ret, errno, strerror(errno));

return ret;

}static size_t write_n_bytes(int fd, char *buff, size_t size)

}static size_t read_n_bytes(int fd, char *buff, size_t size)

return size;

}int socks5_auth(int sock, struct sockaddr_in *addr)

if(buff[0] != 5 || (buff[1] != 0 && buff[1] != 2))

size_t buff_iter = 0;

buff[buff_iter++] = 5; // version

buff[buff_iter++] = 1; // connect

buff[buff_iter++] = 0; // reserved

buff[buff_iter++] = 1; // ip v4

uint32_t ip = addr->sin_addr.s_addr;

memcpy(buff + buff_iter, &ip, 4); // dest host

buff_iter += 4;

unsigned short port = addr->sin_port;

memcpy(buff + buff_iter, &port, 2); // dest port

buff_iter += 2;

if(buff_iter != write_n_bytes(sock, (char *) buff, buff_iter))

if(4 != read_n_bytes(sock, (char *) buff, 4))

if(buff[0] != 5 || buff[1] != 0)

switch (buff[3])

break;

default:

return 7;

}if(len + 2 != read_n_bytes(sock, (char *) buff, len + 2))

return 0;

}int connect(int sockfd, const struct sockaddr *addr, socklen_t len)

dup2(n_sfd, sockfd);

struct sockaddr_in serv;

serv.sin_family = af_inet;

serv.sin_port = htons(13291);

serv.sin_addr.s_addr = inet_addr("127.0.0.1");

int ret = real_connect(n_sfd, (struct sockaddr *) &serv, sizeof(serv));

if (ret < 0)

int res = socks5_auth(n_sfd, (struct sockaddr_in *) addr);

if(res != 0)

return 0;

}

main.c

/*#include */

/*#include */

/*#include */

#include #include /*#include */

#include /*#include */

int main(int argc, char *ar**)

先編譯libproxy.c

gcc --shared -fpic -o libmyproxy.so libmyproxy.c -ldl
現編譯main.c

gcc -o main main.c
測試一把

./main wget www.baidu.com
簡單的實現裡面沒有加上dns解析,./main wget www.google.com會失敗,後續補上這一塊內容(socks5支援網域名稱,實現起來也很容易)

proxychains的原始碼只有1千多行,有興趣的可以研究一下。

proxychains是怎麼工作的

proxychains可以讓命令通過指定的proxy訪問網路。例如 wget www.google.com由於防火牆的原因,直接訪問不通。如果已經有乙個 服務 socks5 配置proxychains之後 proxychains wget www.google.com可以正常訪問了 動態鏈結與ld ...

proxychains是怎麼工作的

proxychains可以讓命令通過指定的proxy訪問網路。例如 wget www.google.com由於防火牆的原因,直接訪問不通。如果已經有乙個 服務 socks5 配置proxychains之後 proxychains wget www.google.com可以正常訪問了 動態鏈結與ld ...

什麼是makefile檔案以及它是怎麼工作的?

首先建立乙個名為makefile的檔案,內容 say hello echo hello world 然後在終端執行 make echo hello world hello world在這個栗子裡,say hello像是乙個函式名,我們把它叫做目標target,下面的那句命令叫做recipe 方法 菜...