100行PHP代码实现socks5代理服务器

2025-05-29 0 83

前两天在B站上看到一个小伙纸100元组装个电脑打LOL画质流畅,突发奇想100行代码能(简单)实现个啥好玩的。我主要是做php开发的,于是就有了本文。

当然,由于php(不算swoole扩展)本身不擅长做网络服务端编程,所以这个代理,只是个玩具,离日常使用有点距离。如果想使用稳定可靠的加密(所以能禾斗学上网)代理,可以用这个:https://github.com/momaer/asocks-go也是100来行代码使用go实现。

写的过程中发现php多线程还是难的。比如我开始想每个连接新建一个线程。但这个线程得保存起来(比如保存到数组),比如官方例子中的这个:https://github.com/krakjoe/pthreads/blob/master/examples/SocketServer.php要放到$clients这个数组里,不然,你试试(curl -L一个要301的地址)就知道出现什么情况了。

这个例子说了in the real world, do something here to ensure clients not running are destroyed 但是,如何把不再运行的连接销毁却没有讲。恩。我试了把$clients放到一个类里,把类传给线程类,然后在线程类要结束时把$clients里对应的连接给unset掉,无果。

那,以下就是使用线程池来实现的代理,按道理讲,退出时池要shutdown(),监听socket也要shutdown的,但百行代码,就不勉强了,随着ctrl + c,就让操作系统来回收资源吧。

php不擅长网络编程体现在哪里呢?首先我用的是stream_socket_XXX相关的函数,为啥不用socket扩展呢?因为socket扩展有问题,参见:https://github.com/krakjoe/pthreads/issues/581而stream_set_timeout对stream_socket_recvfrom这些高级操作,不起作用,参见:http://php.net/manual/en/function.stream-set-timeout.php而这些,在写代理时都需要考虑的。比如连接远程目标服务器时,没有超时控制,很容易就线程池跑满了。

测试的话,使用curl即可,对了,目前只支持远程dns解析,为啥呢?因为这个玩具后期可是要实现禾斗学上网的哟: curl —socks5-hostname 127.0.0.1:1080http://ip.cn

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99
Class Pipe extends Threaded

{

private $client;

private $remote;

public function __construct($client, $remote)

{

$this->client = $client;

$this->remote = $remote;

}

public function run()

{

for ( ; ; ) {

$data = stream_socket_recvfrom($this->client, 4096);

if ($data === false || strlen($data) === 0) {

break;

}

$sendBytes = stream_socket_sendto($this->remote, $data);

if ($sendBytes <= 0) {

break;

}

}

stream_socket_shutdown($this->client, STREAM_SHUT_RD);

stream_socket_shutdown($this->remote, STREAM_SHUT_WR);

}

}

Class Client extends Threaded

{

public $fd;

public function __construct($fd)

{

$this->fd = $fd;

}

public function run()

{

$data = stream_socket_recvfrom($this->fd, 2);

$data = unpack('c*', $data);

if ($data[1] !== 0x05) {

stream_socket_shutdown($this->fd, STREAM_SHUT_RDWR);

echo '协议不正确.', PHP_EOL;

return;

}

$nmethods = $data[2];

$data = stream_socket_recvfrom($this->fd, $nmethods);

stream_socket_sendto($this->fd, "\\x05\\x00");

$data = stream_socket_recvfrom($this->fd, 4);

$data = unpack('c*', $data);

$addressType = $data[4];

if ($addressType === 0x03) { // domain

$domainLength = unpack('c', stream_socket_recvfrom($this->fd, 1))[1];

$data = stream_socket_recvfrom($this->fd, $domainLength + 2);

$domain = substr($data, 0, $domainLength);

$port = unpack("n", substr($data, -2))[1];

} else {

stream_socket_shutdown($this->fd, STREAM_SHUT_RDWR);

echo '请使用远程dns解析.', PHP_EOL;

}

stream_socket_sendto($this->fd, "\\x05\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00");

echo "{$domain}:{$port}", PHP_EOL;

$remote = stream_socket_client("tcp://{$domain}:{$port}");

if ($remote === false) {

stream_socket_shutdown($this->fd, STREAM_SHUT_RDWR);

return;

}

$pool = $this->worker->pipePool;

$pipe1 = new Pipe($remote, $this->fd);

$pipe2 = new Pipe($this->fd, $remote);

$pool->submit($pipe1);

$pool->submit($pipe2);

}

}

class ProxyWorker extends Worker

{

public $pipePool;

public function __construct($pipePool)

{

$this->pipePool = $pipePool;

}

}

$server = stream_socket_server('tcp://0.0.0.0:1080', $errno, $errstr);

if ($server === false)

exit($errstr);

$pipePool = new Pool(200, Worker::class);

$pool = new Pool(50, 'ProxyWorker', [$pipePool]);

for( ; ; ) {

$fd = @stream_socket_accept($server, 60);

if ($fd === false)

continue;

$pool->submit(new Client($fd));

}

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 100行PHP代码实现socks5代理服务器 https://www.kuaiidc.com/98830.html

相关文章

发表评论
暂无评论