国外的检测节点很容易获得,但是国内的就比较难,原因在于国内接入需要备案,但是如果仅仅是自用的话,其实家里的服务器也可以用来作为检测节点。
目前已知最新的阻断方式是针对特定端口的,所以传统的Ping测试或针对80的TCP检测都已经失效。
下面就如何在家用服务器上配置检测节点进行说明
主要内容如下
- 使用FRP进行内网穿透
- 设置目标服务器的返回内容
- 配置本地检测服务
使用FRP进行内网穿透
家用服务器有一个特点就是通常在防火墙后端,为了安全考虑,并不建议在防火墙上开启UPNP或DMZ,因为不可控因素太多。所以在不对防火墙进行任何修改的前提下,就要使用FRP进行安全的内网穿透。
FRP的使用在官方文档已有详细说明,我们首先需要一台主机配置并运行FRPS,然后在本地服务器上配置并运行FRPC,FRP是二进制文件,无需安装,下载后即可使用。
FRP的核心是配置文件,下面的[required]需要替换为实际内容
FRPS.ini
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 |
[common] bind_addr = 0.0.0.0 bind_port = 7000 bind_udp_port = 7001 kcp_bind_port = 7000 proxy_bind_addr = 0.0.0.0 vhost_http_port = 7000 vhost_https_port = 7000 vhost_http_timeout = 60 dashboard_addr = 0.0.0.0 dashboard_port = 7500 dashboard_user = [required] dashboard_pwd = [required] log_file = frps.log log_level = debug log_max_days = 7 token = [required] heartbeat_timeout = 90 allow_ports = [required] max_pool_count = 20 max_ports_per_client = 0 subdomain_host = [required] tcp_mux = true |
记得在服务器的UFW打开对应7000端口,因为这里用了http的端口复用,所以只需要开一个7000端口就可以,管理和通信都是用的7000端口。
subdomain_host用于给frp服务指定独立的域名,这样在服务端apache反代的时候才可以区分frp流量
FRPC.ini
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[common] server_addr = [required] server_port = 7000 tls_enable = true log_file = frpc.log log_level = debug log_max_days = 7 token = [required] user = [required] protocol = tcp [web] type = http local_ip = 127.0.0.1 local_port = 80 subdomain = [required] host_header_rewrite = [required] header_X-From-Where = frp |
host_header_rewrite用于在本地apache反代时区分穿透流量,如果使用tcp协议+端口,则无需这行
完成后,在客户端frpc所在目录新建一个frpc_run.sh,在服务端新建一个frps_run.sh
frpc_run.sh
1 2 3 4 5 |
#!/bin/bash cd `dirname $0` eval $(ps -ef | grep "[0-9] \\./frpc" | awk '{print "kill "$2}') ulimit -n 512000 nohup ./frpc -c ./frpc.ini >> frp.log 2>&1 & |
frps_run.sh
1 2 3 4 5 |
#!/bin/bash cd `dirname $0` eval $(ps -ef | grep "[0-9] \\./frps" | awk '{print "kill "$2}') ulimit -n 512000 nohup ./frps -c ./frps.ini >> frp.log 2>&1 & |
并赋予这两个文件和frp执行文件744权限,
运行frps和frpc
在服务器和客户端分别运行frps_run.sh和frpc_run.sh
接着在服务器端的apache中新建一个反代站点,域名就是配置文件中设置的frp域名,反代目标为本地7000端口
通过绑定的域名访问,如果没有在本地为frp流量建立站点,那么访问后就会显示apache的默认站点,就说明配置完成了
接着在本地的apache中新建一个反代站点,域名是frpc设置的host_header_rewrite,反代目标就是本地的检测服务地址
设置目标服务器的返回内容
因为检测服务需要一个内容反馈来判断是否访问成功,所以需要在目标服务器上配置内容反馈。
SSR服务内置了一个默认反馈内容的配置项
1 |
"redirect": ["any-website-name-like-baidu.com"], |
把这个配置项开启后,所有对SSR的普通访问都会返回设置的网站内容,也就满足了我们需要的检测返回内容的功能。
配置本地检测服务
完成了检测通道和返回内容的配置,接下来就是本地服务器上的后台服务了,可以用很多方法来实现,主要的功能就是将frp传来的请求分析出地址并对地址进行访问,并将访问的返回结果反馈给frp来源。
这里以php举例,使用了guzzlehttp/guzzle插件
test_tcp_request.php
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 |
<?php require __DIR__.'/vendor/autoload.php'; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use GuzzleHttp\Handler\CurlHandler; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; use GuzzleHttp\Psr7; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\ClientException; use GuzzleHttp\Exception\BadResponseException; if (isset($_GET['url']) && $_GET['url'] != '') { $url = $_GET['url']; }else{ $url = 'http://baidu.com'; } $handler = new CurlHandler(); $stack = HandlerStack::create($handler); // Wrap w/ middleware $client = new Client(['handler' => $stack]); $jar = new \GuzzleHttp\Cookie\CookieJar; $onRedirect = function( RequestInterface $request, ResponseInterface $response, UriInterface $uri ) { }; try { $res = $client->request('GET', $url, [ 'cookies' => $jar, 'timeout' => 3, 'http_errors' => true, 'allow_redirects' => [ 'max' => 10, // allow at most 10 redirects. 'strict' => true, // use "strict" RFC compliant redirects. 'referer' => true, // add a Referer header 'protocols' => ['http','https'], // only allow https URLs 'on_redirect' => $onRedirect, 'track_redirects' => true ] ]); $load_json["code"] = $res->getStatusCode(); } catch (RequestException $e) { $load_json["code"] = '0'; $load_json["code"] = $e->getCode(); $load_json["msg"] = $e->getMessage(); } $outputJSON = json_encode($load_json); echo $outputJSON; |
请求地址:
http://subdomain.subdomain_host/test_tcp_request.php?url=baidu.com
http://subdomain.subdomain_host/test_tcp_request.php?url=google.com
返回值:
1 2 3 4 |
baidu.com: {code: 200} google.com: {code: 0,msg: "cURL error 28: Connection timed out after 3000 milliseconds (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)"} |
接着就可以在服务器端调用这个检测节点的API接口了。
一般调用的流程如下
请求:http://subdomain.subdomain_host/test_tcp_request.php?url=节点地址:服务端口
返回:code=0异常,code=200正常。
There are no comments yet