如何在函数计算内部中自定义 DNS 解析

前言

很多时候为了做代码调试,我们有需求将某个域名所映射的地址临时映射成其他 IP。

例如我们需要 mock 某个三方服务代码的异常情况,我们可能自己构造一个 HTTP server,实现异常代码返回,用于函数计算中对该异常的处理。

在本地调试的环境下,通常我们最直接的做法是修改 /etc/hosts 文件,例如:

127.0.0.1 localhost
255.255.255.255 broadcasthost

127.0.0.1 api.example.com

如果修改 /etc/hosts 则需要 root 权限,如果在多用户共享的Linux机器上,直接修改这个还会干扰其他开发人员的正常使用,如何做到普通用户级别的自定义 DNS 解析呢?

实现原理

我们知道,无论 python/node/php 在底层解析 DNS 时最终会调用 glibc 动态链接库中的函数 getaddrinfogethostbyname,最终会尝试读取 /etc/hosts 文件来做解析。那么有没有办法把默认的这个路径给改掉呢?

当然,我们可以 hook C 语言的动态链接库,将对应这些函数给换掉。

在函数计算中,用户所拥有的 user 是普通账号权限,要实现类似的功能也可以利用这个原理来做,接下来这里介绍一下在函数计算中的如何自定义 DNS 解析。

具体实现

    1. 我们先找到 Linux 系统中 /lib/x86_64-linux-gnu/libnss_files.so.2
    1. 将这个文件 copy 一份到项目的根目录中
    1. 用 vim 打开根目录的这个文件
    1. 找到 /etc/hosts (注意到这里是10个字节),并改成为 /code/host (这里也需要是10个字节,不多不少)
    1. 在代码根目录再加一个名为 host (注意是 host 而非 hosts)的文件,里面格式和 /etc/hosts 一样
    1. 更新函数代码
    1. 在函数计算的控制台上为函数增加环境变量:
    • keyLD_LIBRARY_PATH
    • value/code/

对于想偷懒的同学,可以直接点击 libnss_files.so.2 (MD5 = a47453fafb5ec540ba91b6347ec9d82e) 直接下载,跳过第1-4步。

更多参考

除了 LD_LIBRARY_PATH 这个环境变量,我们之前在 这里 还介绍过如何通过 LD_PRELOAD 来实现 全局无入侵网络代理 ,这两个环境变量都可以起到类似的作用。

猜你喜欢

转载自yq.aliyun.com/articles/680746