细说请求转发
一、从伪装说起
伪装是指将一个物体或实体包装成另外一种物体或实体的外观、形态或性质,以达到欺骗或迷惑他人的目的。伪装通常是为了逃避敌人或取得某种优势而进行的行为。
伪装既可以是动物、植物等生物在自然环境中采取的保护措施,也可以是人类在军事、情报、反情报等领域采取的策略手段。
在生物学中,伪装被称为拟态。例如一些昆虫或动物的身体颜色和图案可以模仿周围环境的颜色和纹理,以便更好地藏匿、躲避天敌,提高生存能力。
在军事、情报领域中,伪装是一种常用的战术手段。士兵、情报人员等可以伪装成敌方或中立方士兵、平民、商人等,混入对方组织,从内部获取情报或实施破坏。此外,还有一种隐蔽伪装,即通过改变行为习惯、语言、口音等方式来隐藏真实身份,以达到保密或欺骗的目的。
总之,伪装不是贬义词,是个体通过某种方式改变外貌特征、声音、技能等等,让其拥有某种群体或者另外一个个体身份的能力,可以用来躲避危险、获得某种受限资源等等。
1.特洛伊木马木马是希腊神话中的一个传说,据传说是公元前12世纪发生在古代特洛伊城战争期间的故事。当时,希腊人和特洛伊人之间的战争已经持续了10年,但希腊联军迟迟无法攻破特洛伊城,陷入了长期的困境。
于是,希腊国王阿伽门农想出了一个计策:他派遣了一支精英部队,悄悄地制造了一个巨大的木马,然后将这个木马放置在特洛伊城门口,并假装撤退。特洛伊人看到希腊人的船只离开后,以为战争结束了,便将这个大木马带进城中,庆祝胜利的到来。
然而,深夜里,希腊人从木马的内部钻了出来,放火焚烧特洛伊城门,为希腊联军打开了进攻的大门。最终,特洛伊城被攻破,希腊人获得了战争的胜利。
单从神话故事来讲,希腊军队通过伪装的形式,让士兵们拥有了木马的外形特征,扰乱了特洛伊城的常规安检规则,从而进入特洛伊城,攻破了城池。
2.变色龙 变色龙是著名的伪装专家之一。它们拥有独特的色素细胞,可以使身体表面的颜色和图案随意调整,以适应周围环境的变化。
当变色龙需要隐藏身形时,它们会变成与周围环境颜色相近或相同的颜色,并配合身体姿势,将自己完全融入周围环境中,形成一种“隐形”的效果,这样天敌就很难察觉它们的存在。
当变色龙想要吸引异性或威慑敌人时,它们会改变身体颜色来表达不同的情感状态。例如,当变色龙激动或愤怒时会变红色或黑色,当它感到害怕或温顺时则会变成较浅的颜色。
通过灵活的色彩变化和身体姿势的调整,变色龙可以实现高度的伪装和欺骗效果,是自然界中令人惊叹的伪装大师。
变色龙通过独有的身体结构,根据环境的变化来改变自身的颜色,究根结底是为了生存,遇到危险时与环境融为一体隐藏和保护自己,愤怒时变成具有威慑力的颜色,达到虚张声势和恐吓的效果。
3.请求转发 有时候访问某些服务会受到限制,比如ip白名单、单ip访问频率、ip区域等,无论是出于ip防抓诉求,还是解决ip受限诉求,这时候我们可能需要通过某些具有特定身份的ip中转请求,这样就能解决原始ip请求受限的问题。
细化到具体应用场景,常见的有以下几个:
三方服务对接只有某些ip加白,那么在自身服务能力扩充之后,会有新的非白名单ip发送请求诉求,那么相比于频繁调整白名单,不如用某些固定加过白的ip作为中转站,转发原始请求,从而解决访问受限问题。服务自我保护,互联网环境复杂多变,有些机器不想在公网环境暴露特征,那么就可以通过代理的方式转发请求,这样的话真遇到竞对或者有心之人,抓产品和服务特征也只能摸到中转”瞎子“机器。网络爬虫,有时候出于一些特定诉求,需要在网络上爬取一些内容用来分析,而一般成型的网站都有反爬机制,大多都是封ip和限ip请求频率,那么在合规的前提下,可以适当的准备一些相对散列的中转ip池解决受限问题。二、请求转发解决了什么问题? 代理转发请求有很多应用场景和解决的问题,下面列举了一些主要的应用场景:
1.访问被限制的网站 在某些国家或组织中,一些网站可能会被屏蔽或禁止访问。此时,可以使用代理服务器将请求发送到其他国家或地区的服务器上,并返回响应结果,以达到访问受限网站的目的。
2.提高访问速度 某些代理服务器可能会使用缓存技术,将之前的请求结果缓存下来,当未来需要相同请求结果时,直接从本地缓存中获取响应结果,而无需再次请求源服务器,从而提高访问速度。
3.屏蔽特定内容 通过代理服务器,可以对请求进行过滤,屏蔽一些不适当或非法的内容,保护用户的隐私和安全。
4.负载均衡 代理服务器可以将请求分发到多个后端服务器上,以实现负载均衡,提高服务的可用性和性能。
5.隐藏真实IP地址 某些应用程序需要隐藏真实的IP地址,以避免被攻击者或其他人利用。使用代理服务器进行请求转发,可以隐藏真实IP地址,并提高安全性。
6.检查请求 某些代理服务器可以对请求进行检查,并根据一些预定义规则进行访问控制,从而保护用户的安全。
7.监控和记录 代理服务器还可以对所有流经它的请求进行监控和记录,以便记录访问日志、统计分析和安全审计等。
8.绕过防火墙 在企业内部网络中,可能会存在防火墙等安全设施,导致某些网站无法正常访问。使用代理服务器可以绕过此类安全设施,实现访问目标网站的目的。
9.分流或重定向 代理服务器可以根据不同的请求分发到不同的后端服务器上,也可以将请求重定向到其他网站或应用程序上,实现不同的应用场景。
总的来说,代理转发请求是一种非常灵活和强大的技术,代理转发请求可以帮助用户访问被限制的网站,提高访问速度和服务质量,提高安全性和隐私保护等,可以涵盖很多不同的应用场景和解决问题的方法,并为用户提供更安全、更快速、更高效的服务。
三、请求转发如何实现再强大的应用场景也需要基础的理论支撑,再强大的理论也都需要应用场景来验证其可行性和体现其价值。接下来我们就列举一下请求转发常用的实现方式和方案。
1.RestTemplateRestTemplate是Spring自带的http请求客户端,准备一个代理机器并且开放指定端口,通过如下代码来实现请求代理转发:
代码语言:javascript复制// 创建 HttpClientBuilder 实例
HttpClientBuilder builder = HttpClientBuilder.create();
// 设置代理服务器地址和端口
HttpHost proxy = new HttpHost("host", port, "http");
builder.setProxy(proxy);
// 构建 HttpClient 对象
CloseableHttpClient client = builder.build();
// 构建用于传输 HTTP 请求的 ClientHttpRequestFactory
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(client);
RestTemplate restTemplate = new RestTemplate(factory);
// 构建 HTTP 请求对象
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XHTML_XML);
HttpEntity
// 向目标主机的 API 发送 HTTP 请求,并获取响应结果
ResponseEntity
System.out.println(responseEntity.getBody());可以看到,本机在不需要代理机器账密的情况下,只知道ip和端口,就能免密让其作为肉鸡转发请求。
2.HttpClient基于apache的httpclient客户端可以使用如下代码实现请求代理转发:
代码语言:javascript复制 HttpClient httpClient = HttpClientBuilder.create().build();
HttpHost proxy = new HttpHost("host", port);
RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
HttpGet request = new HttpGet("https://www.baidu.com");
request.setConfig(config);
try {
HttpResponse response = httpClient.execute(request);
log.info("status={}",response.getStatusLine().getStatusCode());
} catch (IOException e) {
log.error("occur error",e);
}同样,本机在知道代理机器ip和端口的请求下,不需经过任何账密和证书认证,就能让其转发请求,而请求接收端追溯请求来源也大概率只能追溯到代理机器。
3.OkHttpOkHttp也提供了请求代理转发的能力,比较简单的实现如下:
代码语言:javascript复制 OkHttpClient client = new OkHttpClient().newBuilder()
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("host", port)))
.build();
Request request = new Request.Builder()
.url("http://www.baidu.com")
.build();
try {
Response response = client.newCall(request).execute();
log.info("success={},body={}",response.isSuccessful(),response.message());
} catch (IOException e) {
log.error("occur error",e);
}4.java自带http客户端java也有自带的http请求客户端,实现起来比三方工具稍稍负载一些,不过也能满足请求代理转发的诉求,实现如下:
代码语言:javascript复制 URL url = new URL("https://www.baidu.com");
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("13.251.26.58", 9000));
HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);
// 设置请求方法和请求头
connection.setRequestMethod("GET");
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
// 发送请求并获取响应
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
System.out.println(response.toString());5.nginx当然nginx除了作为业务网关能力之外,也可以实现请求代理转发的能力,和前边几种方式不同的地方是,nginx可以单独作为服务器来承担转发能力,不用关心客户端基于哪种类型,只需把请求发给nginx即可,然后nginx负责原样把请求转发给目标接口。
代码语言:javascript复制server {
listen port;
server_name host or domain;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://target_host; # 这里为目标服务ip或域名
}
}6.ssh反向隧道通过反向SSH隧道,可以将本地端口映射到远程服务器上的某个端口,从而实现请求的转发。具体方法是在本地机器上运行ssh命令,将要代理的端口转发到远程机器上的一个端口,然后在程序中使用这个端口来进行请求。
代理机器需要安装ssh(默认安装),开启接受来自SSH客户端的反向隧道连接:
代码语言:javascript复制GatewayPorts yes
AllowTcpForwarding yes
# 重启sshd生效
systemctl start sshd.service另外代理机器也要开启22端口远程登录,ssh反向隧道连接本质上走的是22端口的ssh协议。
本地启动ssh反向代理:
代码语言:javascript复制ssh -R 8080:localhost:80 user@proxy_host8080是指远程服务器上的端口,localhost是指本地机器上的主机名或IP地址,80是指本地机器上的端口号。user是指远程服务器上的用户名,proxy_host是指远程服务器的主机名或IP地址。开启后本地程序通过80端口发送的请求都会从代理机器8080端口转发出去。
7.ALB以aws alb为例,配置alb并转发到目标服务,并且alb支持转发到外部公网ip,需要注意的是,如果不需要暴露客户端ip,那么可以关闭X-Forwarded-For,alb是通过X-Forwarded-For获取客户端真实ip的。
8.CDN通常来讲,CDN多用于静态内容加速,有些场景也可以用来做动态接口加速,那么CDN是如何实现请求转发的呢?
其实很简单,创建CDN分配的时候,把源站改成目标请求ip或者域名就行了,需要注意的是,对于一些写请求或者数据经常变更的读请求,要调整缓存策略,极端情况下不需要CDN提供缓存能力,只是作为一个请求转发中转站。
四、如何防范公网ip被用来转发其实这里有两个概念,首先是如何防范公网ip被抓,然后是如何防范公网ip被用来转发。
1.防范公网ip被抓非必要不暴露公网ip:对于很多服务器,承担的更多能力是业务处理,不需要直接接收来自公网的请求,对于需要访问公网资源的场景,走统一的公网出口,类似办公局域网,能访问公网,但是出口ip是同一个。关闭公网端口:对于业务服务机器,其实可以关闭所有公网访问端口,包括22、80和443端口,对于有公网连接这些端口程序的诉求,可以通过vpn、跳板机以及云服务负载均衡器来做内网穿透。使用网络安全设备:使用网络安全设备,例如防火墙、入侵检测系统(IDS)和入侵预防系统(IPS),可以有效地防范公网 IP 被扫描和攻击。这些设备可以检测并封锁来自可疑来源的攻击流量,以及针对特定服务和协议的攻击。监控日志:在服务器上开启安全日志,并及时监控和分析日志,发现并阻止可疑的访问行为。可以使用工具,例如 fail2ban、osquery 等。不过这种方式只是辅助手段,有点后知后觉的感觉。2.防范公网ip被用来转发关闭非必要的端口:关闭端口的公网访问能力,如果出于某种原因某些端口无法关闭,那么从该端口出去的请求,对于敏感业务,必须要有足够充分的身份认证,比如令牌和签名等。关闭ssh反向隧道:代码语言:javascript复制sshd -T | grep "GatewayPorts"
sshd -T | grep "AllowTcpForwarding"如果返回yes就是开启状态,需要关闭:
代码语言:javascript复制vim /etc/ssh/sshd_config
GatewayPorts no
AllowTcpForwarding no
systemctl restart sshd上述配置关闭后不会影响到ssh协议连接。
关闭服务器的转发能力:
代码语言:javascript复制
#修改sysctl.conf配置
vi sysctl.conf
net.ipv4.ip_forward=0
# 载入新的sysctl配置,使其生效
sysctl -pnet.ipv4.ip_forward=0 表示关闭了 Linux 操作系统的 IP 转发功能。当此参数的值为 0 时,Linux 操作系统会禁止将网络数据包从一个网络接口转发到另一个网络接口。
这个参数的作用是用于防止 Linux 服务器被用于攻击,因为攻击者可以通过开启 IP 转发功能,将发起的攻击流量转发到其他网络进行攻击,从而给目标网络带来安全隐患。因此,关闭 IP 转发功能可以提高服务器的安全性。
关闭 IP 转发功能只会影响该服务器将来自本地网络的数据包转发到其他网络的能力,不会影响本机发送网络请求能力。
五、思考前边所描述的核心是如何自己安全的做好转发,并且防止自己的服务器变成公网转发的肉鸡,其实就是需要满足自己的请求转发诉求,并关闭公网转发的能力,安全的做好请求转发。
1.访问控制
请求转发的功能可能会使得内部服务暴露到公网,因此需要对访问进行控制。转发能力对自己的服务器群组开放,对公网关闭。
2.认证和授权对于一些敏感资源,需要进行认证和授权。可以使用基于身份验证和访问控制的流程来管理请求转发,并且只允许授权用户进行访问。
3.日志审计针对转发的流量进行日志审计,记录所有的连接及其相关细节,以方便审计、排查和追踪问题,同时也有助于检测潜在的攻击行为。
4.加密传输对于一些敏感信息,需要加密传输以防止数据泄露。如果请求转发的流量中包含敏感数据,需要使用https加密协议来保护数据安全。
5.漏洞管理对于转发的目标服务器,需要定期检查并修复可能存在的安全漏洞,以保障被转发的内部服务不受攻击和转发服务器变成肉鸡。总之,我们需要通过各种安全手段来协同保障请求转发功能的安全性。这些策略可以帮助我们减少安全风险,提高服务稳定性和可用性。