如何在函数计算中实现无入侵全局网络代理

本文涉及的产品
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
函数计算FC,每月15万CU 3个月
简介: ## 什么场合需要代理? 假设您有一台物理服务器部署在家里,你需要在函数计算中访问这台物理服务器。最简单的办法是直接暴露这个物理服务器到公网环境。那么问题来了,如果直接暴露到公网不设置防火墙,那么任何人都可以直接访问你的机器,这样会有很大风险。

什么场合需要代理?

假设您有一台物理服务器部署在家里,你需要在函数计算中访问这台物理服务器。最简单的办法是直接暴露这个物理服务器到公网环境。那么问题来了,如果直接暴露到公网不设置防火墙,那么任何人都可以直接访问你的机器,这样会有很大风险。由于函数计算的 IP 是动态变化的,所以您也无法做到指定某个范围的 IP 做防火墙限制。

我们换个思路,将函数计算的的出口访问请求全部经过一台或多台 ECS 出口代理,然后再向外发出请求。ECS和函数计算之间使用加密,那么上面的问题就可以解决了。

如何将函数计算的出口请求全部使用网络代理?

方案一:改源码

将所有相关请求的 client 加上代理服务器地址。

这个方案最大的问题是需要改变原有逻辑,成本非常高,对于既有 binary 代码无法做出修改。

很显然,这并不是一个好方案。

方案二:使用 http_proxy 环境变量

使用 http_proxy, all_proxy, https_proxy, no_proxy 等环境变量。

我们知道函数计算支持用户自定义环境变量,我们可以将代理服务器的地址写入环境变量,那么这个函数中所有的 HTTP 请求都会被转发到这个代理服务器做跳转请求。我们可以通过 no_proxy 来控制部分host 不走代理。

例如:

http_proxy=http://username:passwd@123.100.10.123:3128
no_proxy=.aliyun.com,.taobao.com

优点:

无需改动任何一行代码,增加一项环境变量即可。甚至对于既有的 binary 文件,只要遵循 http_proxy 代理协议无需做任何改动即可以正常执行。

缺点:

虽然现有的大部分 HTTP client 遵循这个规范,但还是有一些实现并不遵从,更重要的是,某些网络请求根本不是 HTTP 协议,例如 MySQL client 可能用的是 TCP 连接。

方案三:非入侵式动态替换 glibc 的 connect 函数

如何使用 proxychains

我们先编译这个项目

git clone https://github.com/haad/proxychains
./configure && make 

找到 libproxychains.soproxychains.conf

我们在现有函数计算代码包中,增加 proxy 目录,将 libproxychains.soproxychains.conf 放置到该目录,修改 proxychains.conf 中代理服务器的地址和相关用户密码,如果有不需要代理的 HOST 也可以在该文件中配置。

注意到,这里我们可以使用 http / https / socks4 / socks5 等多种代理协议。

创建函数后,我们在函数计算的控制台上为这个函数增加两个环境变量:

PROXYCHAINS_CONF_FILE=/code/proxy/proxychains.conf
LD_PRELOAD=/code/proxy/libproxychains4.so

我们可以使用下面的代码做测试:

# -*- coding: utf-8 -*-
import os

def handler(event, context):
    os.system('curl -v ipinfo.io')
    return 'hello world'


if __name__ == '__main__':
    handler(1, 1)

通过上述函数,我们在日志中可以得到当前函数访问出口 IP。

优点:

  • 原生程序无需关系代理协议细节
  • 所有的 TCP 请求都可以无缝地使用代理,逻辑代码可以无感知,无侵入;
  • 支持自定义 DNS;

缺点:

  • 需要为原始工程增加 proxy 目录,增加两个文件;
  • 不支持 UDP 协议代理;

对于大部分项目来说,使用 UDP 的地方相当少,而只是增加两个文件即可以做到全局代理,这些缺点可以忽略了

实现原理

我们需要在 client 发起 connect 的时候把实际要连接的服务器重定向到指定代理服务器, write 对应 socket fd 的时候将原始数据做相关代理封包,写给代理服务器,read 的时候尝试把代理数据包解开写回给应用逻辑层。

在理解上述实现之前,我们先来看一个示例,如何替换编译好的 C 语言可执行程序中的函数 printf,将下面的 hello world!\n 替换成 hello world!\nhello FC!\n

#include <stdio.h>

int main(int argc, char *argv[]) {
    puts("hello world!\n");
}

我们把这个编译好

gcc -o a.out main.c

执行得到 hello world!\n

实现 hook.c

#define _GNU_SOURCE
#include <dlfcn.h>

typedef int (*origin_puts_t)(const char *msg);

int puts(const char *msg) {
    int n = 0;
    origin_puts_t origin_puts;
    
    /* find the origin puts function */
    origin_puts = (origin_puts_t)dlsym(RTLD_NEXT, "puts");
    
    /* use origin puts to print message */
    n += origin_puts(msg);
    n += origin_puts("hello FC!\n");
    return n;
}

编译动态链接库 hook.so :

gcc -shared -fPIC  hook.c -o hook.so -ldl

接下来我们设置环境变量,并执行原来的 a.out :

LD_PRELOAD=$PWD/hook.so ./a.out

输出得到:

hello world!
hello FC!

也就是说,我们将 a.outputs 函数替换成了 hook.so 中的 puts

了解这个原理后,我们回到原来的问题,如何实现无入侵的网络代理?

参考 libproxychains.so 核心实现:

connect

代理服务器的搭建

推荐 3proxy

  • 支持带验证的 socks4/socks5/HTTP 代理
  • 支持多账号
  • 支持账号流量控制
  • 支持 linux/mac/windows
  • 支持 DNS 代理查询
  • 支持 IPv6
  • 配置简单
相关实践学习
【文生图】一键部署Stable Diffusion基于函数计算
本实验教你如何在函数计算FC上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。函数计算提供一定的免费额度供用户使用。本实验答疑钉钉群:29290019867
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
目录
相关文章
|
4月前
|
消息中间件 存储 Serverless
函数计算产品使用问题之怎么访问网络附加存储(NAS)存储模型文件
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
5月前
|
缓存 数据安全/隐私保护 Kotlin
Kotlin 中的网络请求代理设置最佳实践
Kotlin 中的网络请求代理设置最佳实践
|
7月前
|
监控 安全 网络安全
漏洞扫描系统可以用于发现网络入侵者?
漏洞扫描系统自动检测系统安全漏洞,如未打补丁软件和弱密码,但无法直接发现网络入侵者。入侵者可能使用加密和掩盖手段逃避检测。为此,需结合入侵检测系统(IDS)、防火墙、安全事件管理(SIEM)系统和蜜罐等工具实时监控异常行为。企业还应提升员工安全意识以增强防御能力。
|
4月前
|
缓存 负载均衡 应用服务中间件
【揭秘】nginx代理配置全攻略:从零到精通,一文带你玩转高效网络代理的秘密武器!
【8月更文挑战第22天】nginx是一款高性能的HTTP与反向代理服务器,支持代理服务、负载均衡及缓存等功能,有助于提升网站响应速度和安全性。首先需确保已安装nginx,可通过包管理器进行安装。安装后启动并确认nginx运行状态。接着编辑配置文件(通常位于`/etc/nginx/nginx.conf`),设置代理转发规则,例如指定目标服务器地址和请求头信息。配置完成后测试有效性并重新加载nginx以应用更改。可以通过部署简易HTTP服务器验证代理功能是否正常工作。此外,还可以通过扩展配置文件实现更复杂的代理需求,如基于路径的代理和SSL加密等。
584 2
|
4月前
|
缓存 负载均衡 应用服务中间件
Nginx 代理管理器强势登场!轻松设置反向代理,为你的网络安全与高效护航,快来探索!
【8月更文挑战第23天】Nginx 代理管理器(NPM)是一款强大的工具,用于简化反向代理的设置流程。反向代理能隐藏后端服务器的真实IP,提升安全性,实现负载均衡与缓存等功能。用户需先安装Nginx 代理管理器,然后通过其Web界面添加代理主机,指定代理名称、协议类型、服务器地址及端口等信息。对于HTTPS协议,还需上传SSL证书/密钥。完成设置后,可通过浏览器测试反向代理是否正常工作。Nginx 代理管理器还支持高级特性,如负载均衡、缓存及访问控制等。
115 1
|
4月前
|
缓存 负载均衡 网络协议
Haskell网络编程:深入理解代理和TLS配置
Haskell网络编程:深入理解代理和TLS配置
|
6月前
|
机器学习/深度学习 Serverless 文件存储
函数计算操作报错合集之在网络设置完成后进行挂载的指令,报错:找不到网络路径,该如何处理
在使用函数计算服务(如阿里云函数计算)时,用户可能会遇到多种错误场景。以下是一些常见的操作报错及其可能的原因和解决方法,包括但不限于:1. 函数部署失败、2. 函数执行超时、3. 资源不足错误、4. 权限与访问错误、5. 依赖问题、6. 网络配置错误、7. 触发器配置错误、8. 日志与监控问题。
|
6月前
|
数据采集 Java 数据安全/隐私保护
使用Java进行网络采集:代理IP与参数传递详解
Java参数传递是按值传递,包括对象引用的值。当传递对象时,方法内部修改对象内容会影响原始对象,但不能改变原始引用。示例展示了如何在爬虫代理中使用此机制,通过`ProxySettings`类传递代理信息,方法内可访问但不能更改原始对象。理解这一机制对编写高效无错的Java代码至关重要。
使用Java进行网络采集:代理IP与参数传递详解
|
6月前
|
安全 网络安全
IPXProxy代理提升网络安全:私人住宅IP的高匿名性
​在现代数字环境中,保护在线隐私和安全已成为关键问题。每次我们在网上浏览时,都会留下数据痕迹,这些痕迹可能被用来跟踪我们的活动,甚至有些网站会禁止访问我们的IP地址。为了保护上网安全并确保网络活动顺利进行,许多个人和企业转向使用私人住宅IP。那么,什么是私人住宅IP,它的高匿名性体现在哪些方面?
|
6月前
|
缓存 Java Scala
Scala网络编程:代理设置与Curl库应用实例
Scala网络编程:代理设置与Curl库应用实例

热门文章

最新文章

相关产品

  • 函数计算