草庐IT

真-全局代理原理细谈

Ikarosxx 2023-04-13 原文

全局代理

以下讨论仅针对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.protocol.http.HttpURLConnection$HttpInputStream@66133adc


    }
}


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)可以看到

有关真-全局代理原理细谈的更多相关文章

  1. ruby - 在 RSpec 中 stub /模拟全局常量 - 2

    我有一个gem,它有一个根据Rails.env的不同行为的方法:defself.envifdefined?(Rails)Rails.envelsif...现在我想编写一个规范来测试这个代码路径。目前我是这样做的:Kernel.const_set(:Rails,nil)Rails.should_receive(:env).and_return('production')...没关系,只是感觉很丑。另一种方法是在spec_helper中声明:moduleRails;end而且效果也很好。但也许有更好的方法?理想情况下,这应该有效:rails=double('Rails')rails.sho

  2. ruby - 将全局 $stdout 重新分配给控制台 - ruby - 2

    我正在尝试将$stdout设置为临时写入一个文件,然后返回到一个文件。test.rb:old_stdout=$stdout$stdout.reopen("mytestfile.out",'w+')puts"thisgoesinmytestfile"$stdout=old_stdoutputs"thisshouldbeontheconsole"$stdout.reopen("mytestfile1.out",'w+')puts"thisgoesinmytestfile1:"$stdout=old_stdoutputs"thisshouldbebackontheconsole"这是输出。r

  3. ruby - HTTP 请求中的用户代理,Ruby - 2

    我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)

  4. ruby-on-rails - capybara poltergeist - 覆盖用户代理 - 2

    有人知道如何将capybarapoltergeist的用户代理覆盖到移动用户代理以进行测试吗?我发现了一些有关为seleniumwebdriver配置它的信息:http://blog.plataformatec.com.br/2011/03/configuring-user-agents-with-capybara-selenium-webdriver/这在capybara闹鬼中怎么可能? 最佳答案 请参阅poltergeistgithub页面上的链接:https://github.com/teampoltergeist/polte

  5. ruby - 如何配置 Ruby Mechanize 代理以通过 Charles Web 代理工作? - 2

    我正在使用Ruby/Mechanize编写一个“自动填写表格”应用程序。它几乎可以工作。我可以使用精彩CharlesWeb代理以查看服务器和我的Firefox浏览器之间的交换。现在我想使用Charles查看服务器和我的应用程序之间的交换。Charles在端口8888上代理。假设服务器位于https://my.host.com。.一件不起作用的事情是:@agent||=Mechanize.newdo|agent|agent.set_proxy("my.host.com",8888)end这会导致Net::HTTP::Persistent::Error:...lib/net/http/pe

  6. ruby - 在模块/类之间共享全局记录器 - 2

    在许多ruby​​类之间共享记录器实例的最佳(正确)方法是什么?现在我只是将记录器创建为全局$logger=Logger.new变量,但我觉得有更好的方法可以在不使用全局变量的情况下执行此操作。如果我有以下内容:moduleFooclassAclassBclassC...classZend在所有类之间共享记录器实例的最佳方式是什么?我是以某种方式在Foo模块中声明/创建记录器还是只是使用全局$logger没问题? 最佳答案 在模块中添加常量:moduleFooLogger=Logger.newclassAclassBclassC..

  7. ruby - Sinatra 中的全局救援和日志记录异常 - 2

    如何在出现异常时指定全局救援,如果您将Sinatra用于API或应用程序,您将如何处理日志记录? 最佳答案 404可以在not_found方法的帮助下处理,例如:not_founddo'Sitedoesnotexist.'end500s可以通过调用带有block的错误方法来处理,例如:errordo"Applicationerror.Plstrylater."end错误的详细信息可以通过request.env中的sinatra.error访问,如下所示:errordo'Anerroroccured:'+request.env['si

  8. ruby - 如何捕获所有 HTTP 流量(本地代理) - 2

    我希望访问我机器上的所有HTTP流量(我的Windows机器-不是服务器)。据我了解,拥有一个本地代理是所有流量路线的必经之路。我一直在谷歌搜索但未能找到任何资源(关于Ruby)来帮助我。非常感谢任何提示或链接。 最佳答案 WEBrick中有一个HTTP代理(Rubystdlib的一部分)和here's一个实现示例。如果你喜欢生活在边缘,还有em-proxy伊利亚·格里戈里克。这postIlya暗示它似乎确实需要一些调整来解决您的问题。 关于ruby-如何捕获所有HTTP流量(本地代理)

  9. ruby - 为什么允许在 Ruby 类之外定义全局方法? - 2

    我读过这个:Let’sstartwithasimpleRubyprogram.We’llwriteamethodthatreturnsacheery,personalizedgreeting.defsay_goodnight(name)result="Goodnight,"+namereturnresultend我的理解是,方法是定义在类中的函数或子程序,可以关联到类(类方法)或对象(实例方法)。那么,如果它不是在类中定义的,怎么可能是方法呢? 最佳答案 当你在Ruby中以这种方式在全局范围内定义一个函数时,它在技术上变成了Obje

  10. ruby - Sinatra 路由中定义的全局变量是否在请求之间共享? - 2

    假设我有:get'/'do$random=Random.rand()response.body=$randomend如果我每秒有数千个请求到达/,$random是否会被共享并“泄漏”到上下文之外,或者它会像getblock的“本地”变量一样?我想如果它是在get'/'do的上下文之外定义的,它确实会被共享,但我想知道在ruby​​中是否有我不知道的$机制。 最佳答案 ThispartoftheSinatraREADMEaboutscopeisalwayshelpfultoread但是,如果您只需要为请求保留变量,那么我认为我建议使用

随机推荐