第一次尝试也没关系🙆♂️在生产环境中运行Nginx容器时的安全防护措施很重要
首先
尽管Nginx在许多产品和服务中得到使用,但我发现了一些安全设置方面难以理解的地方,因此进行了一番调查。
在使用Nginx进行安全措施时,还有许多其他方法,
但本次重点介绍了在将其用作实际生产容器时绝对需要采取的基本配置。
我們在文件公式中也簡單提到了,但現在我們打算更詳細地進行解釋。
此外,我們將以默認的nginx配置文件為基礎進行解說。
https://hub.docker.com/_/nginx
以非root用户身份启动
包括Nginx在内的许多Docker镜像默认以root用户启动。
root用户具有所有操作的权限,如果不慎允许该用户入侵容器,
则可能导致主机操作也可以使用root权限执行,非常危险。
不仅容器,基本上应避免以root权限运行服务器。
以nginx用户启动
实际上,我在Dockerfile中指定了用户为nginx,并创建了容器。
FROM nginx:latest
USER 101 #nginxのUID
# USER nignx でも大丈夫です!
如果构建映像完成后,不需要root权限,所以我尝试使用nginx用户进行启动,但出现了以下错误…
除了nginx映像外,大多数映像只需要创建并指定非root用户就可以启动,
但似乎nginx不能只凭此就能启动… ?(幸运的是,似乎nginx用户已经默认创建了)
- nginxユーザーを指定したときのエラー
docker run -u nginx -p 80:80 nginx:1.17.8-alpine ✘ 1
[warn] 1#1: the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:2
nginx: [warn] the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:2
[emerg] 1#1: mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
看起来还需要进一步创建Dockerfile和进行nginx配置,以便可以使用nginx用户进行启动。我希望逐步进行解释。
更改待机端口
当以默认方式启动nginx时,默认使用80端口作为监听端口。但是,从0到1023端口被称为知名端口,对于使用这些端口,需要root权限。(参考:什么是知名端口)
因此,要在非root权限下启动nginx,需要将监听端口指定为1024之后的端口。
这次我们将通过修改/etc/nginx/conf.d/default.conf配置文件,使nginx在8080端口上进行监听。
修改nginx的配置
server {
listen 8080; # <- この部分を変更
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
修改Docker的端口
通过之前的设置,容器中的Nignx将在8080端口启动。
默认的Nginx镜像的容器端口设置为80号端口,因此需要将其调整为Nginx的监听端口8080号。
另外,在构建镜像时,需要添加设置以便将之前创建的文件导入。
COPY源文件的名称和路径可以随意设置,但是COPY的目标路径应指定为/etc/nginx/conf.d/default.conf。
FROM nginx:latest
COPY default.conf /etc/nginx/conf.d/default.conf
EXPOSE 8080
USER 101
在上述的设置中,我们现在可以在不需要root权限的端口号上启动容器了!但是,
设置文件权限以便nginx用户能够启动。
Nginx的默认配置将pid信息和各种临时文件的输出路径设置为root用户拥有的文件夹。由于nginx用户没有写入这些文件的权限,所以需要将输出路径设置为任何用户都可以读写的文件夹,如/tmp目录。具体设置如下:
# user nginx; <- マスタープロセスがroot起動時の設定なのでなくても大丈夫です
worker_processes auto;
error_log /var/log/nginx/error.log warn;
#変更前 pid /var/run/nginx.pid;
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;
include /etc/nginx/conf.d/*.conf;
}
为了使Dockerfile能够导入以上文件,我们需要添加相应的配置。目标目录为/etc/nginx/nginx.conf。
此外,为了使缓存能够写入,我们将向nginx用户授予对/var/cache/nginx的写入权限。
FROM nginx:latest
COPY nginx.conf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf
RUN chown -R 101:0 /var/cache/nginx \
&& chmod -R g+w /var/cache/nginx
USER 101
我终于成功地用以上的设置以Nginx用户身份启动了容器?。
以只读模式启动
使用Docker启动容器时(run)可以指定只读模式,这样可以防止对容器的写入,并且能够防止篡改。
以下是先前创建的Dockerfile在读取模式下构建并启动容器的命令示例。
docker build -t nginx-non-root:latest .
docker run -p 8080:8080 --read-only -v $(pwd)/tmp:/tmp/ nginx-non-root:latest
感受到的感觉
回头看,我发现有相当多的设置项目?
尽管有设置说明在官方 dockerHub 上列出,
但是没有解说,所以我把它们整理成备忘录了。
如果有任何不恰当的部分、考虑不周的地方,或者有办法使其更易理解的建议,我会很高兴听取。
赠品
我在这里努力写了这篇文章,但是我在这里创建的Docker镜像已经由志愿者创建好了…
很麻烦。如果你想快速获取配置文件,可以使用以下命令?
docker pull nginxinc/nginx-unprivileged
DockerHub: DockerHub镜像链接为https://hub.docker.com/r/nginxinc/nginx-unprivileged
GitHub: GitHub代码仓库链接为https://github.com/nginxinc/docker-nginx-unprivileged
附赠2
我每天都在传递非常有益的信息。或许有一天,Nginx容器在生产环境中的安全措施会变得比较重要?。
256人想要女朋友— ぐしゃ@ 自由职业云工程师 (@gusya_the_fool) 2020年4月3日