惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
爱范儿
爱范儿
J
Java Code Geeks
L
LangChain Blog
V
V2EX
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
博客园 - Franky
Microsoft Azure Blog
Microsoft Azure Blog
Jina AI
Jina AI
Blog — PlanetScale
Blog — PlanetScale
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The Cloudflare Blog
博客园 - 司徒正美
B
Blog
G
Google Developers Blog
Stack Overflow Blog
Stack Overflow Blog
罗磊的独立博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Apple Machine Learning Research
Apple Machine Learning Research
Engineering at Meta
Engineering at Meta
MyScale Blog
MyScale Blog
有赞技术团队
有赞技术团队
Hugging Face - Blog
Hugging Face - Blog

小松鼠的博客

记录一次线上k8s工作节点无法创建容器的问题排查思路与解决办法 记一次线上GoLang项目OOM排查过程 从LastPass转向拥抱开源KeePass的心路历程 故障定位与 AI 结合前后端编码实践 FileBeat收集nginx-ingress-controller日志 K8s云原生环境下文件描述符占用过高查询思路 2024年最新关闭火绒安全工具的开机自启方法 Kubernetes任务调度实践-Go语言实现Job和CronJob对比分析 离线更新k8s环境下的trivy漏洞库方法 使用Go语言接入Choerodon实现基于OAuth2的统一身份认证登录 在Vue2中自定义Switch组件并实现父子组件双向数据绑定 关于docker jdk1.8镜像中的GB18030-2022标准支持及验证 Go框架gin中的session存储gin-contrib-sessions和go-session 关于修改node_module中的源码问题记录 docker-compose网络和内网服务IP冲突问题 慎用存储过程:一条语句引发的数据库存储100%占用 Spring Boot中4种文件下载方法的实现 避坑-不能将specific类型的gitlab-runner改变为share类型 Docker compose中的MySQL主从复制模式和percona-toolkit工具使用 在minio中开启https访问以及使用rclone备份minio桶 在多机Docker环境下部署Choerodon的解决方案 Prometheus中Monitor添加对SpringBoot Actuator的Basic认证 K8s中的两种nginx-ingress-controller及其区别 两个docker工具:runlike和whaler Grafana中的邮件报警和截图插件grafana-image-enderer K8s中externalName-service和services-without-selectors maven配置文件settings.xml中的一些概念总结 K8s中flexvolume插件驱动的安装 K8s中的coredns无法解析svc问题排查 K8s中使用Ingress访问请求体过大问题解决
在Nginx的容器镜像中隐藏Nginx的Server响应头
ycyin · 2023-01-11 · via 小松鼠的博客

2023年1月10日大约 3 分钟云原生DockerNginx


前端应用部署在K8s中,Nginx以容器的方式运行。由于一些安全因素,我们需要将Nginx返回的响应头中Server隐藏掉不让访问者知道我们的服务器信息(包括服务器类型和版本号)。

方案

对于隐藏版本号,我们可以在配置文件中,http区段中插入server_tokens off;后重新载入配置文件即可实现。

对于隐藏服务类型,目前了解到有两种方案:方案一是修改源码,重新编译Nginx;方案二是加载headers-more-nginx-module这个模块。因为我们是在容器中运行的Nginx,所以我们考虑方案二更为简单。

实现

通过二次docker build镜像,将headers-more-nginx-module这个模块的so文件,放到/etc/nginx/modules/目录下,然后在nginx.conf中第一行添加load_module /etc/nginx/modules/ngx_http_headers_more_filter_module.so; 动态加载这个模块。(注意:动态加载模块在nginx1.9.11之后支持)

首先,我们可以在prebuilt-nginx-modules[1]这个库中找到大佬编译的关于加载nginx模块的prebuilt镜像;

然后在这个prebuilt镜像基础上打出我们自己需要对应版本的so模块文件[2],并使用一个特殊的空镜像scratch,将我们的构建产物保留,以供后面生产环境的镜像快速复用拿到我们的so模块文件:

注意:NGINX_VERSION和MODULE_VERSION的版本对应,写这篇文章时headers-more-nginx-module[3]只发布了0.34版本最高支持nginx1.22.0

我也将这个镜像放到了dockerhub中:yinyicao/headers-more-nginx-module:1.22.0-0.34

ARG NGINX_VERSION=1.22.0
FROM soulteary/prebuilt-nginx-modules:base-${NGINX_VERSION} AS Builder

ARG MODULE_VERSION=0.34
ARG MODULE_NAME=headers-more-nginx-module

COPY ${MODULE_NAME}-${MODULE_VERSION}.tar.gz /usr/src/v${MODULE_VERSION}.tar.gz
RUN cd /usr/src && \
    tar -zxC /usr/src -f v${MODULE_VERSION}.tar.gz && \
    cd /usr/src && \
    mv ${MODULE_NAME}-${MODULE_VERSION}/ ${MODULE_NAME} && \
    cd /usr/src/nginx && \
    CONFARGS=$(nginx -V 2>&1 | sed -n -e 's/^.*arguments: //p') \
    CONFARGS=${CONFARGS/-Os -fomit-frame-pointer -g/-Os} && \
    echo $CONFARGS && \
    ./configure --with-compat --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -ffile-prefix-map=/data/builder/debuild/nginx-1.22.0/debian/debuild-base/nginx-1.22.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie' --add-dynamic-module=../${MODULE_NAME}/ && \
    make modules
FROM scratch
COPY --from=Builder /usr/src/nginx/objs/ngx_http_headers_more_filter_module.so /

最后,只需要根据我们要用的nginx基底镜像,将生成的ngx_http_headers_more_filter_module.so这个文件复制到nginx的模块目录并在nginx.conf中加载即可。

FROM nginxinc/nginx-unprivileged:1.22.0

USER 0

# Modify timezone
ENV TZ=Asia/Shanghai

RUN apt-get update; \
    apt-get install -y --no-install-recommends \
        vim \
        curl \
        ca-certificates; \
    apt-get upgrade -y --no-install-recommends; \
    rm -rf /var/lib/apt/lists/*;

# Nginx conf
ADD default.conf /etc/nginx/conf.d/default.conf
ADD nginx.conf /etc/nginx/nginx.conf

# aliyun mirror
RUN cp /etc/apt/sources.list /etc/apt/sources.list.bak; \
    sed -i 's http://.*.debian.org http://mirrors.aliyun.com g' /etc/apt/sources.list

RUN echo 'root:changeit' | chpasswd

# 从上一个镜像中复制ngx_http_headers_more_filter_module.so,headers-more-nginx-module:1.22.0-0.34就是上一个Dockerfile打出来的镜像名
COPY --from=headers-more-nginx-module:1.22.0-0.34 /ngx_http_headers_more_filter_module.so /etc/nginx/modules/

不要忘了提前在nginx.conf中使用load_module加载这个模块:

load_module /etc/nginx/modules/ngx_http_headers_more_filter_module.so;

worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /tmp/nginx.pid;


events {
    worker_connections  1024;
}


http {
    proxy_temp_path /tmp/proxy_temp;
    client_body_temp_path /tmp/client_temp;
    fastcgi_temp_path /tmp/fastcgi_temp;
    uwsgi_temp_path /tmp/uwsgi_temp;
    scgi_temp_path /tmp/scgi_temp;

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;
    more_clear_headers 'Server';

    include /etc/nginx/conf.d/*.conf;
}

这样打出来的nginx镜像在访问时的响应头中就不会有Server信息了。

参考:


  1. https://hub.docker.com/r/soulteary/prebuilt-nginx-modules ↩︎

  2. https://soulteary.com/2021/03/22/how-to-use-nginx-third-party-modules-efficiently-in-the-container-era.html ↩︎

  3. https://github.com/openresty/headers-more-nginx-module ↩︎