搭建HTTP内网文件服务器-以NGINX为例

需求

在内网建一个文件服务器,需要示意图如下:

实现需求,可行的组件:

1
2
3
4
5
apache http
tomcat/jetty
nginx
.....

为方续架构扩展(如做反向代理等)、扩展功能的丰富性和个人对组件的熟悉程度,最终选择了Nginx.

nginx 搭建文件服务

这里需要使用到Nginx的autoindex 特性(ngx_http_autoindex_module 模块),以及其它几个module。由于本文涉及到Nginx的多个版本的不同feature ,建议nginx安装版本为: 1.18.0 + ,详情参照Nginx Changes

nginx install

1
2
3
wget http://nginx.org/packages/rhel/7/x86_64/RPMS/nginx-1.18.0-2.el7.ngx.x86_64.rpm
sudo yum install nginx-1.18.0-2.el7.ngx.x86_64.rpm -y
nginx -V

修改配置

配置nginx config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
user nginx;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
worker_connections 256;
}

http {

sendfile on;
tcp_nopush on;
sendfile_max_chunk 512k;
types_hash_max_size 2048;
# server_tokens off;

# server_names_hash_bucket_size 64;
# server_name_in_redirect off;

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

##
# SSL Settings
##
ssl_protocols TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;

##
# Logging Settings
##
log_format main '$time_local|$remote_addr|$scheme|$host|$status|$request_time|$body_bytes_sent|$request|$remote_user|$http_referer|$http_user_agent|$http_x_forwarded_for';
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

gzip on;

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

server 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
vim /etc/nginx/conf.d/file-server.conf

server {
listen *:80;
server_name localhost;

#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;

# file index
location / {
alias /opt/data/hdp_dir/;
sendfile on;
aio threads=default;

charset utf-8;
autoindex on;
autoindex_exact_size off;
autoindex_format html;
autoindex_localtime on;
}
}

配置文件目录权限

设置文件目录权限

1
2
chown -R nginx:users  /opt/data/hdp_dir/
chmow -R 775 /opt/data/hdp_dir/
  • nginx 重启
    1
    2
    3
    4
    5
    6
    7
    #开机启动
    systemctl enable nginx

    # 启动
    systemctl restart nginx
    systemctl status nginx

  • 测试
    1
    curl -XGET "http://127.0.0.1:80'
    文件服务搭建完毕。如下图:

提升IO性能

由于大并发的大文件下载,磁盘IO会最先成为瓶颈。所以这里对IO进行优化,增加aio 和 sendfile tcp_nopush tcp_nodelay 用以提升IO性能. 以下载一个10G文件为例子,从实际测试效果对比看,磁盘的IO压力的下降了很多,如下图:

按照官网的Thread Pools in NGINX Boost Performance 9x!,性能可以提升9倍。 AIO配置说明,参照 nginx aio .

增加文件预览

实现对配置允许的文件格式后缀,文件可以打开,可以下载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
location / {
alias /opt/data/hdp_dir/;
sendfile on;
aio threads=default;
charset utf-8;
autoindex on;
autoindex_exact_size off;
autoindex_format html;
autoindex_localtime on;
#file shows
if ($request_filename ~* ^.*?\.(txt|doc|pdf|rar|gz|zip|docx|exe|xlsx|ppt|pptx)$){
add_header Content-Disposition: 'p_w_upload;';
}
}

总结

  • index.html文件冲突 Nginx autoindex 可能会遇到目录下有 index.html 文件,出现401Error Object问题,可以采用下面的方法解决:

    1
    2
    # 对目录下的 index.html文件进行重命名
    find ./ -type f -name "index.html" -exec mv {} {}-bak \;

    修改完成后可能需要nginx 服务。

  • 权限控制 如果需要设置权限控制,可以使用ngx_http_access_module, 需要用户鉴权还可用设置HTTP Basic Authentication. 对于需要多租户的场景,可以配置 Basic HTTP authentication,参考nginx用户认证配置( Basic HTTP authentication

  • 文件搜索 对于需要使用搜索功能,可以使用 ngx-fancyindex) 插件,实现效果如下图:

  • 传输安全 如果涉及敏感数据传输,建议增加TLS1.2+协议进行加密传输

  • 为什么不用FTP实现 FTP不是一项安全的协议,并且具有许多安全漏洞。比如存在暴力破解、FTP反弹攻击。在加上FTP使用的端口是21,一般会被防火墙屏蔽。(yum 等repository 仓库默认使用的都是HTTP协议)

参考