前言
很多时候为了做代码调试,我们有需求将某个域名所映射的地址临时映射成其他 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 动态链接库中的函数 getaddrinfo
或 gethostbyname
,最终会尝试读取 /etc/hosts
文件来做解析。那么有没有办法把默认的这个路径给改掉呢?
当然,我们可以 hook C 语言的动态链接库,将对应这些函数给换掉。
在函数计算中,用户所拥有的 user 是普通账号权限,要实现类似的功能也可以利用这个原理来做,接下来这里介绍一下在函数计算中的如何自定义 DNS 解析。
具体实现
-
- 我们先找到 Linux 系统中
/lib/x86_64-linux-gnu/libnss_files.so.2
- 我们先找到 Linux 系统中
-
- 将这个文件 copy 一份到项目的根目录中
-
- 用 vim 打开根目录的这个文件
-
- 找到
/etc/hosts
(注意到这里是10个字节),并改成为/code/host
(这里也需要是10个字节,不多不少)
- 找到
-
- 在代码根目录再加一个名为
host
(注意是host
而非hosts
)的文件,里面格式和/etc/hosts
一样
- 在代码根目录再加一个名为
-
- 更新函数代码
-
- 在函数计算的控制台上为函数增加环境变量:
-
key
为LD_LIBRARY_PATH
-
value
为/code/
对于想偷懒的同学,可以直接点击 libnss_files.so.2 (MD5 = a47453fafb5ec540ba91b6347ec9d82e) 直接下载,跳过第1-4步。
更多参考
除了 LD_LIBRARY_PATH
这个环境变量,我们之前在 这里 还介绍过如何通过 LD_PRELOAD
来实现 全局无入侵网络代理 ,这两个环境变量都可以起到类似的作用。