1.接口地址配置
我们打开clash的配置主文件夹,找到config.yaml,查看关于api端口和密码的设置。
以下是一个config.yaml文件示例:
mixed-port: 7890
allow-lan: true
external-controller: 127.0.0.1:53365
secret: 29c0c9ba-1740-42c0-bb8c-dd316c5d1e4a
ipv6: false
log-level: info
其中external-controller为API的IP和端口配置,如果需要其他机器能够访问这个接口,需要将IP设置为0.0.0.0,secret为API接口密码。
以下是ClashForWindows打开config.yaml文件夹的方法
2.ClashForWindows常用HTTP接口详细介绍
获取所有代理
GET
/proxies
获取 Clash 中所有的代理200 代理类型: Direct | Reject | Selector | Shadowsocks | Socks5 | URLTest 类型为 Selector 时有 all 和 now 两个字段,分别代表所含有的代理以及现在选中的代理 类型未 URLTest 时 now 字段为现在最快的代理名字
{
"proxies": {
"DIRECT": {
"type": "Direct"
},
"GLOBAL": {
"all": [
"Proxy",
"auto",
"🇭🇰"
],
"now": "Proxy",
"type": "Selector"
},
"Proxy": {
"all": [
"auto",
"🇭🇰"
],
"now": "auto",
"type": "Selector"
},
"REJECT": {
"type": "Reject"
},
"auto": {
"now": "🇭🇰",
"type": "URLTest"
},
"🇭🇰": {
"type": "Shadowsocks"
}
}
}
获取单个代理的延迟
GET
/proxies/:name/delay
获取 Clash 中单个代理的延迟
Path Parameters
Name | Type | Description |
---|---|---|
name | string | 代理名 (大小写敏感) |
Query Parameters
Name | Type | Description |
---|---|---|
timeout | number | 超时时间 (ms) |
url | string | 测试代理的目标网址 |
返回状态码:200 正常返回、400请求格式错误、404代理不存在、408代理请求超时
{
"delay": 200
}
切换 Selector 中选中的代理
PUT
/proxies/:name
当前接口只支持切换 Selector 中的代理
Path Parameters
Name | Type | Description |
---|---|---|
name | string | 代理名称 (大小写敏感) |
Request Body
Name | Type | Description |
---|---|---|
name | string | 要切换的代理名字 |
返回状态码:204 切换成功、400请求错误、404代理不存在
获得当前的基础设置
GET
/configs
{
"port": 7890,
"socket-port": 7891,
"redir-port": 0,
"allow-lan": true,
"mode": "Rule",
"log-level": "info"
}
增量修改配置
PATCH
/configs
传入需要修改的配置即可
Request Body
Name | Type | Description |
---|---|---|
port | integer | HTTP 代理端口 |
socks-port | integer | Socks5 代理端口 |
redir-port | string | Redir 代理端口 |
allow-lan | boolean | 是否把代理监听地址放到 0.0.0.0 |
mode | string | 代理模式 ( Global | Rule | Direct ) |
log-level | string | 设置 TTY 日志等级 ( info | warning | error | debug ) |
返回状态码:204 由于可能出现 RESTful API 流量经过代理的问题,而更换端口需要 Graceful Shutdown 所以统一返回 204 No Content
3.自动换IP方法
参考上述常用API接口,我们可通过”GET/proxies
获取所有代理”和”PUT
/proxies/:name
切换 Selector 中选中的代理”两个接口结合,完成自动获取代理节点,随机更换当前代理节点。(为获取活跃且低延迟的节点,可能需要增加一个定时任务,通过”GET
/proxies/:name/delay
延迟获取”方法更新节点延迟信息。)
以下是一个java版实现Clash切换IP的功能,此处使用了hutool工具类库。需要提前引入相关的maven依赖。
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ClashUtil {
private static final Logger log = LoggerFactory.getLogger(ClashUtil.class);
/**
* clash配置
* external-controller: 127.0.0.1:61920
* secret: 4a1c185f-607e-4ec6-a984-bab952503d5d
*/
public static String clashApiUrl = "http://172.17.0.1:61920";
public static String socks5ProxyHost = "172.17.0.1";
public static int socks5ProxyPort = 7891;
public static String secret = "4a1c185f-607e-4ec6-a984-bab952503d5d";
//public static String secret = "";
public static String selectorName = "GLOBAL";
public static String curNode = null;
public static final List<String> excludeNodes = Arrays.asList(new String[]{"自动选择","故障转移","实验","免费","国内","漏网","Cloudflare"
,"Steam","选择","爱奇","动画","DIRECT","REJECT","OneDrive"});
public static List<String> getAllNode(){
HttpRequest request = HttpUtil.createGet(clashApiUrl+"/proxies");
if(StrUtil.isNotEmpty(secret)){
request.header("Authorization","Bearer "+secret);
}
String result = request.execute().body();
if(StrUtil.isEmpty(result) || !JSONUtil.isTypeJSONObject(result)){
return null;
}
JSONObject resultObj = JSONUtil.parseObj(result).getJSONObject("proxies");
JSONArray jsonArray = resultObj.getJSONObject(selectorName).getJSONArray("all");
List<String> validNodeList = new ArrayList<>();
for (int i = 0; i < jsonArray.size(); i++) {
String itemNodeName = jsonArray.getStr(i);
boolean isExcludeNodes = false;
for (String excludeNode : excludeNodes) {
if(itemNodeName.contains(excludeNode)){
isExcludeNodes = true;
break;
}
}
if(isExcludeNodes){
continue;
}
boolean use = true;
//延迟计算
JSONObject nodeDelay = resultObj.getJSONObject(itemNodeName);
//失效节点
if(nodeDelay==null || nodeDelay.getJSONArray("history")==null || nodeDelay.getJSONArray("history").size()==0){
continue;
}
int maxDelay = 1000;
JSONArray delayArray = nodeDelay.getJSONArray("history");
for (int i1 = 0; i1 < delayArray.size(); i1++) {
JSONObject itemDelay = delayArray.getJSONObject(i1);
Integer itemDelayInt = itemDelay.getInt("delay");
if(itemDelayInt>maxDelay || itemDelayInt==0){
use = false;
break;
}
}
if(use){
//System.out.println(itemNodeName);
validNodeList.add(itemNodeName);
}
}
return validNodeList;
}
public static void testAllNode(){
HttpRequest request = HttpUtil.createGet(clashApiUrl+"/proxies");
if(StrUtil.isNotEmpty(secret)){
request.header("Authorization","Bearer "+secret);
}
String result = request.execute().body();
if(StrUtil.isEmpty(result) || !JSONUtil.isTypeJSONObject(result)){
return ;
}
JSONObject resultObj = JSONUtil.parseObj(result).getJSONObject("proxies");
JSONArray jsonArray = resultObj.getJSONObject(selectorName).getJSONArray("all");
for (int i = 0; i < jsonArray.size(); i++) {
String itemNodeName = jsonArray.getStr(i);
boolean isExcludeNodes = false;
for (String excludeNode : excludeNodes) {
if(itemNodeName.contains(excludeNode)){
isExcludeNodes = true;
break;
}
}
if(isExcludeNodes){
continue;
}
//测速
try {
HttpUtil.get(clashApiUrl+"/proxies/"+ URLEncodeUtil.encodeAll(itemNodeName) +"/delay?timeout=5000&url=http%3A%2F%2Fwww.gstatic.com%2Fgenerate_204", 10000);
} catch (Exception e) {
}
}
}
public static boolean changeRandomNode(){
List<String> allNode = getAllNode();
if(CollectionUtil.isEmpty(allNode) || allNode.size()<10){
log.error("not enough node for change");
return false;
}
String selectNode = RandomUtil.randomEle(allNode);
HttpRequest request = HttpUtil.createRequest(Method.PUT,clashApiUrl+"/proxies/"+ selectorName);
request.header("Authorization","Bearer "+secret);
JSONObject requestBodyObj = new JSONObject();
requestBodyObj.putOnce("name",selectNode);
request.body(requestBodyObj.toString());
HttpResponse response = request.execute();
if(response.getStatus()==204){
curNode = selectNode;
log.info("change node success:{}",selectNode);
return true;
}
log.error("change node error,:{}",response.body());
return false;
}
public static void main(String[] args) {
changeRandomNode();
}
}
自动换IP功能可广泛用于自动化注册、网络爬虫等场景。