HTTP和SOCKS5代理和区别
HTTP和SOCKS5是两种常见的代理协议,它们在数据传输方式和使用场景上有一些不同。
- HTTP代理:HTTP代理主要用于HTTP协议的数据传输,它在客户端和服务器之间起到一个中间人的作用,帮助用户获取、发送数据。HTTP代理只处理HTTP和HTTPS的网络流量,因此主要用于网页浏览等场景。HTTP代理可以读取并修改传输的数据,还可以对HTTP头进行操作,因此使用时要注意隐私和安全问题。
- SOCKS5代理:SOCKS5代理是一个更高级的协议,它支持任何类型的网络流量,包括TCP和UDP,因此可以用于更多的场景,如FTP、SMTP等各种应用层协议。SOCKS5代理只负责将数据包从源传输到目标,不关心数据的内容,因此它对数据包的处理更少,速度更快,但也意味着它不能提供像HTTP代理那样的数据修改功能。SOCKS5代理还支持各种身份验证方法,因此在安全性上比HTTP代理更有优势。
总的来说,HTTP代理和SOCKS5代理的主要区别在于数据处理方式和使用范围。HTTP代理主要用于处理HTTP/HTTPS流量,可以修改数据,但安全性较低;SOCKS5代理可以处理任何类型的网络流量,数据处理少,速度快,安全性较高。
HTTP代理默认会在HTTP请求头中加上源IP,容易泄露自身IP。SOCKS5匿名性较高。
准备工作
1.设置Clash代理端口
默认是7890端口,同时支持HTTP和SOCKS5,一般可不修改。
2.设置Clash restfull API端口
在主界面点击Home Directory主目录项的“Open Folder”打开文件夹,进入配置根文件目录下。
右边编辑config.yaml文件,查看external-controller一项的配置。以下是一个配置示例:
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表示Clash HTTP API的接口地址。如果需要让局域网访问,可将IP调整为0.0.0.0,并且设置allow-lan允许局域网流量。
secret为Clash HTTP API的密码,需要在API请求头加入“Authorization:Bearer ${secret}”。
代码编写
1.程序使用Clash的SOCKS5代理(JAVA为例)
此处使用了OkHttp的工具包,示例代码:
maven依赖引入:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.2</version>
</dependency>
public static Response searchByProxy(String url ){
Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 53365))
try {
// 创建OkHttpClient
client = new OkHttpClient.Builder()
.proxy(proxy)
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.build();
// 创建请求
Request request = new Request.Builder()
.url(url)
.addHeader("Accept-Language", "en-US")
.addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36")
.build();
Response response = client.newCall(request).execute();
return response;
} catch (Exception e) {
log.error("请求失败,error:{}",e.getMessage());
return null;
}
}
2.程序自动换IP
主要过程是使用clash restfull接口获取全部节点,剔除不可用的节点和延迟较高节点,然后使用API换节点。
此处使用了hutool的工具包,引入依赖:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.19</version>
</dependency>
编写工具类:
import cn.hutool.core.collection.CollectionUtil;
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://127.0.0.1:61920";
public static String secret = "4a1c185f-607e-4ec6-a984-bab952503d5d";
public static String selectorName = "GLOBAL";
public static String curNode = null;
public static final List<String> excludeNodes = Arrays.asList(new String[]{"自动选择","故障转移","DIRECT","REJECT"});
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;
}
//延迟计算
JSONObject nodeDelay = resultObj.getJSONObject(itemNodeName);
//失效节点
if(nodeDelay==null || nodeDelay.getJSONArray("history")==null || nodeDelay.getJSONArray("history").size()==0){
continue;
}
int maxDelay = 1000;
boolean use = true;
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 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();//自动换节点
}
}
通过调用changeRandomNode方法完成自动换IP过程。getAllNode方法用于获取所有活跃且低延迟的节点。
正文完