天天看點

真-全局代理原理細談全局代理

全局代理

以下讨论仅针对windows

起因

最近有个朋友问我当我们的代理软件(v2rayn)设置成全局代理后

比如自己写的java程序会不会受代理的影响

扩展一下也可以理解成这里的全局代理是不是真的是全局的

探究

常规

直观来讲,通常我们的代理是在服务器上搭建服务端

本机上搭建客户端

客户端配置好连接

设置本地监听哪个端口

然后在我们的软件上配置代理地址(客户端电脑地址)和端口

软件的流量就会通过客户端

再由客户端进行策略选择进行流量分发

为了避免被拦截

有些代理软件也会对流量进行伪装

如v2rayN

真-全局代理原理細談全局代理

全局

在v2rayN中提供了一个全局代理的选项(不同版本软件叫法不同)

真-全局代理原理細談全局代理

其原理本质上是修改windows系统下的代理设置(可通过注册表)

真-全局代理原理細談全局代理
真-全局代理原理細談全局代理

当我们设置了系统代理后

软件可以选择直接获取系统代理

真-全局代理原理細談全局代理

有些软件默认是使用系统代理的如IE/Edge/Firefox

但如果软件默认不使用系统代理,或者软件不支持设置代理

则我们的系统代理配置是不生效的

这就有了一开始的问题

v2rayN中配置了全局代理,自己写的java程序会不会受代理的影响

这取决于你有没有在java程序里配置

Java代理

可以手动指定

也可以通过

java.net.useSystemProxies

使用系统代理

原生请求
import lombok.extern.slf4j.Slf4j;
import sun.net.www.protocol.http.HttpURLConnection;

import java.io.IOException;
import java.net.URL;

/**
 * @author 许培宇
 * @date 2022/6/1 15:31
 */
@Slf4j
public class Demo {
    public static void main(String[] args) throws Exception {
        String property = System.getProperty("java.net.useSystemProxies");
        log.info("java.net.useSystemProxies:{}", property);
        HttpURLConnection googleConnection = null;
        Object content = null;
        try {
            URL url = new URL("http://www.google.com");
            googleConnection = (HttpURLConnection) url.openConnection();
            googleConnection.setConnectTimeout(3000);
            googleConnection.connect();
            content = googleConnection.getContent();
            log.info("withOutProxy:{}", content);
        } catch (IOException e) {
            log.info("withOutProxy occur error");
        }

        try {
            googleConnection = new HttpURLConnection(new URL("http://www.google.com"), "127.0.0.1", 10809);
            googleConnection.setConnectTimeout(3000);
            googleConnection.connect();
            content = googleConnection.getContent();
            log.info("customProxy:{}", content);
        } catch (IOException e) {
            log.info("customProxy occur error");
        }


        try {

            googleConnection = new HttpURLConnection(new URL("http://www.google.com"), null);
            googleConnection.setConnectTimeout(3000);
            googleConnection.connect();
            content = googleConnection.getContent();
            log.info("systemProxy:{}", content);
        } catch (IOException e) {
            log.info("systemProxy occur error");
        }

        // 输出结果
        // 10:34:36.114 [main] INFO cn.ikarosx.Demo - java.net.useSystemProxies:false
        // 10:34:39.169 [main] INFO cn.ikarosx.Demo - withOutProxy occur error
        // 10:34:39.265 [main] INFO cn.ikarosx.Demo - customProxy:sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@5479e3f
        // 10:34:42.279 [main] INFO cn.ikarosx.Demo - systemProxy occur error

        // java.net.useSystemProxies可以指定使用系统代理参数
        // 需要添加虚拟机启动参数-Djava.net.useSystemProxies=true,不能在代码设置  
        // On recent Windows systems and on Gnome 2.x systems it is possible to tell the java.net stack, setting this property to true, to use the system proxy settings (both these systems let you set proxies globally through their user interface). Note that this property is checked only once at startup.


        // 系统代理输出结果
        // 10:55:49.416 [main] INFO cn.ikarosx.Demo - java.net.useSystemProxies:true
        // 10:55:49.542 [main] INFO cn.ikarosx.Demo - withOutProxy:sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@5479e3f
        // 10:55:49.653 [main] INFO cn.ikarosx.Demo - customProxy:sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@27082746
        // 10:55:49.773 [main] INFO cn.ikarosx.Demo - systemProxy:sun.net.www.proto[email protected]


    }
}


           
RestTemplate
public static void main(String[] args) throws Exception {
    String property = System.getProperty("java.net.useSystemProxies");
    log.info("java.net.useSystemProxies:{}", property);
    RestTemplate restTemplate = new RestTemplate();
    ResponseEntity<String> forEntity = restTemplate.getForEntity("http://www.google.com", String.class);
    System.out.println(forEntity.getStatusCode());

    // 10:59:40.075 [main] INFO cn.ikarosx.Demo - java.net.useSystemProxies:true
    // 10:59:40.346 [main] DEBUG org.springframework.web.client.RestTemplate - HTTP GET http://www.google.com
    // 10:59:40.360 [main] DEBUG org.springframework.web.client.RestTemplate - Accept=[text/plain, application/json, application/*+json, */*]
    // 10:59:40.466 [main] DEBUG org.springframework.web.client.RestTemplate - Response 200 OK
    // 10:59:40.499 [main] DEBUG org.springframework.web.client.RestTemplate - Reading to [java.lang.String] as "text/html;charset=ISO-8859-1"
    // 200 OK

}
           
其他配置

https://docs.oracle.com/javase/8/docs/api/java/net/doc-files/net-properties.html

真全局

那有没有什么办法实现让不支持代理的软件也走代理呢?

ssTap/proxifier/freeCap就可以实现类似的功能

大致是如下几种方案

虚拟网卡

原理是新建一个(Tun/Tap)虚拟网卡

然后修改路由规则

将某些网段的请求经由这个虚拟网卡处理

具体网卡是如何处理的这部分不是很清楚

找了很多资料也没有看不太懂

这里引用一篇文章说的是我们的客户端会监听虚拟网卡

虚拟网卡接收到后会发给我们的客户端去处理

ssTap/vpn/wireguard是这么做的

当我们使用之后可以在网络适配器里查看网卡

可以看到多了一个

route print

可以查看路由表

真-全局代理原理細談全局代理
Winsock LSP劫持

这种方式是proxifier的实现方式

参考文章

原理就是说应用层进行网络通讯时会调用Winsock API

LSP做的就是在中间进行拦截,达到修改等目的

根据这篇文章所说

查看注册表(proxifier v3.42)可以看到

真-全局代理原理細談全局代理

繼續閱讀