nginx-记录

nginx-记录


前篇

  • a

安装


修改默认 web 目录

  1. 修改 /etc/nginx/sites-available/default 文件

    1
    root /webapps/myblog; # root 就是默认目录

常用命令

  • 查看版本

    1
    2
    3
    4
    5
    6
    7
        # nginx -V                       
    nginx version: nginx/1.19.8

    - 优雅关闭 (不接受新的连接请求,等待旧的连接请求处理完毕再关闭)

    ```json
    # nginx -s quit
  • 配置平滑更新

    1
    # nginx -s reload
  • 测试配置文件是否正确

    1
    2
    3
    4
    5
    6
    7
    8
        $ nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful

    - 版本信息

    ```json
    # nginx -v
  • 系统命令

    • 重启服务

      1
      # service nginx restart
    • 启动服务:

      1
      # service nginx start
    • 停止服务

      1
      2
      3
      4
      5
      6
          # service nginx stop

      - 查看状态

      ```json
      # service nginx status

添加配置

在 Nginx 安装目录下的 conf.d 下存放配置, 以 .conf 结尾即可

  • 如:

    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
        [root@hades /etc/nginx/conf.d]# ls
    yx.conf

    [root@hades /etc/nginx/conf.d]# vim yx.conf
    # ipa web 服务
    server {
    listen 32081;
    server_name localhost;
    root /webapps/ipa-web;
    index index.html;
    }



    ---

    ### 测试配置是否正确

    - 命令

    ```json
    $ nginx -t

    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful

tcp 代理配置

  1. 修改 主配置文件 /etc/nginx/nginx.conf , 增加 stream 模块

    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
    39
    40
    41
    42
    43
    44
    user  nginx;
    worker_processes auto;

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


    events {
    worker_connections 1024;
    }


    http {
    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/http_*.conf; # 为了方便区分, 只包含 http_ 开头的文件
    }

    # 增加 stream 模块
    stream {
    log_format proxy '$remote_addr [$time_local] '
    '$protocol $status $bytes_sent $bytes_received '
    '$session_time "$upstream_addr" '
    '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';

    access_log /var/log/nginx/tcp_access.log proxy;
    open_log_file_cache off;

    include /etc/nginx/conf.d/tcp_*.conf; # 为了方便区分, 只包含 tcp_ 开头的文件
    }
  2. /etc/nginx/conf.d 目录下新建一个 tcp_01.conf 文件

    代理到 redis 服务

    1
    2
    3
    4
    server {
    listen 11223;
    proxy_pass 10.0.3.6:6379; # 内网 redis 服务
    }
  3. 测试一下, golang

    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
        func TestConnect(t *testing.T) {
    _, err = redis.Dial("tcp", "aaa.bbb.cn:11223")
    if err != nil {
    panic(err)
    }
    fmt.Printf("--- connect success")
    }



    ---

    ### websocket 代理

    - 在配置中配置, 例如: 反向代理 http://aaa.bbb.com:1234 到 http://ccc.ddd.com:5678

    ```json
    server {
    listen 1234;
    server_name aaa.bbb.com;

    location / {
    proxy_pass http://ccc.ddd.com:5678;
    proxy_http_version 1.1;
    proxy_connect_timeout 15s;
    proxy_read_timeout 30s;
    proxy_send_timeout 30s;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    }
    }

不带 www 重定向 www

  • 参考配置

    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
    # https www web 服务
    server
    {
    listen 443 ssl;
    server_name www.aaa.com;
    root /webapps/my_hexo_blog02/public;
    # root /webapps/myblog;
    index index.html;

    add_header Content-Security-Policy upgrade-insecure-requests;

    # ssl
    ssl_certificate /opt/nginx-cert/any.aaa.com/any.aaa.com.cer;
    ssl_certificate_key /opt/nginx-cert/any.aaa.com/any.aaa.com.key;
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    access_log /var/log/nginx/www.aaa.com.log;
    }

    # http 重定向到 https
    server {
    listen 80;
    server_name www.aaa.com aaa.com;
    return 301 https://www.aaa.com$request_uri;
    }

    # 无 www 重定向到 有 www
    server {
    listen 443;
    server_name aaa.com;
    return 301 https://www.aaa.com$request_uri;
    }

配置密码访问

  1. 生成账号密码文件, 如账号密码为 hello, 123456

    1
    2
    3
    4
    5
    $ echo "hello:$(openssl passwd 123456)" > /opt/nginx_passwd

    // 查看一下密码是加密后的
    $ cat /opt/nginx_passwd
    hello:e6CDcfRjlUN2o
  2. 配置 nginx

    1
    2
    3
    4
    5
    6
    7
    8
    server
    {
    listen 443 ssl;
    location / {
    auth_basic "Some description"; # 加入这两行配置
    auth_basic_user_file /opt/nginx_passwd;
    }
    }
  3. 重载配置

    1
    $ service nginx force-reload

    访问时就需要密码了

    image-20230121135800750


配置不预览直接下载

  1. 有几种方式

    • add_header 加上 Content-Disposition 为 attachment

      1
      2
      3
      4
      5
      6
      location / { 
      if ($request_filename ~* ^.*?\.(txt|doc|pdf|rar|gz|zip|docx|exe|xlsx|ppt|pptx|jpg|png)$){
      add_header Content-Disposition attachment;
      charset utf-8;
      }
      }
    • add_header 加上 Content-Type 为 octet-stream

      1
      2
      3
      4
      5
      6
      7
      location / { 
      if ($request_filename ~* ^.*?\.(txt|doc|pdf|rar|gz|zip|docx|exe|xlsx|ppt|pptx|jpg|png)$){
      # add_header Content-Type "text/plain;charset=utf-8"; # 预览模式
      add_header Content-Type "application/octet-stream;charset=utf-8"; # 下载模式
      charset utf-8;
      }
      }
  1. 重载 nginx 配置

    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
       $ service nginx force-reload

    3. 测试时, 由于游览器有缓存, 所以直接用下载链接测试

    - 直接在浏览器中打开测试链接 https://aaa.bbb.cn/aaa.txt, 修改了配置后, 在浏览器上 *ctrl + R* 强刷, 就可以看到是否是 预览 还是 直接下载



    ---

    ### header 校验

    1. 修改配置文件, 以请求头 *Authorization* 为例

    ```json
    server {
    listen 1234;
    server_name aaa.bbb.cn;

    location / {
    # 校验
    if ($http_Authorization != "aaabbb") { // 验证的 key 值需要带上 http_ 前缀
    return 400 "auth fail!";
    }
    }
  2. 请求

    1
    2
    3
    4
    headers = {
    "Content-Type": "application/json; charset=utf-8",
    "Authorization": "aaabbb",
    }

自定义日志输出

  1. 在 http 块中定义, 也就是在 /etc/nginx/nginx.conf 中定义

    1
    2
    3
    4
    5
    6
    7
    8
    9
    http {
    log_format custom_log_format '$remote_addr - $remote_user [$time_local] '
    '"$request" $status $body_bytes_sent '
    '"$http_referer" "$http_user_agent" '
    '"$http_host" "$http_connection" "$http_accept" '
    '"$http_accept_language" "$http_accept_encoding" '
    '"$http_cache_control" "$http_origin" '
    '"$http_x_forwarded_for" "$http_x_real_ip" aaa'; # 加了个 aaa 测试
    }
    • 在 Nginx 中,log_format 指令只能放在 http 块中,而不能直接放在 server 块或 location 块中。这是因为 log_format 定义的是全局的日志格式,所有 serverlocation 块都可以引用它,但不能在它们里面直接定义。
  2. 在 server 快中引用

    1
    2
    3
    4
    5
    6
    7
    server
    {
    listen 1234 ssl;
    server_name aaa.bbb.com;

    access_log /var/log/nginx/itsapi_6502.wilker.cn.log custom_log_format; # 引用自定义格式
    }
  3. 重载 nginx 配置

    1
    $ service nginx force-reload
  4. done. 请求: https://aaa.bbb.com:1234 就能看到自定义输出

    1
    120.229.3.191 - - [08/Sep/2024:21:00:19 +0800] "GET /favicon.ico HTTP/1.1" 404 18 "https://aaa.bbb.com:1234/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36" "https://aaa.bbb.com:1234" "keep-alive" "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8" "zh-CN,zh;q=0.9,en;q=0.8" "gzip, deflate, br, zstd" "-" "-" "-" "-" aaa

踩坑

中文乱码

  1. 修改配置文件, 设置字符集

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    server {
    listen 81;
    set $root F:/Develop/nginx-1.14.0/html;
    root $root;
    server_name localhost;
    access_log logs/host.access.log main;
    index index.html index.php;
    charset utf-8; #设置字符集
    location / {
    root html;
    index index.html index.htm;
    charset utf-8; #设置字符集
    }
    }
  2. 重新加载配置

    1
    $ nginx -s reload

请求体过大

报错: 413 request entity too large

nginx 默认限制的请求大小, 修改配置

1
2
3
4
5
6
7
8
9
server
{
listen 443 ssl;
server_name aaa.bbb.cn;
location / {
client_max_body_size 32m; # 修改成你需要的大小
proxy_pass http://localhost:25001;
}
}

参考: https://juejin.cn/post/6844904120457887751


tcp stream 配置错误

错误: "stream" directive is not allowed here

  • 原配置文件 /etc/nginx/conf.d/tcp01.conf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    stream {
    upstream mysrv01 {
    server 192.168.1.42:22 weight=50;
    }

    server {
    listen 51901;
    listen 51901 udp;
    proxy_pass mysrv01;
    }
    }

    是指在 nginx 默认配置文件 /etc/nginx/nginx.conf 中的 http 模块包含到了这个 /etc/nginx/conf.d/tcp01.conf 文件, 而 stream 是和 http 是同级的, 所以出现层级错误

    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
        http {
    include /etc/nginx/conf.d/*.conf;
    }

    - 解决办法就是 http 模块中的不要包含到 */etc/nginx/conf.d/tcp01.conf* 文件即可



    ---

    #### 服务获取 ip 一直是 127.0.01

    - 加上 ip 转发配置

    ```json
    server
    {
    location / {
    # 加上这些 ip 配置
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Server $host;

    client_max_body_size 32m;
    proxy_pass http://127.0.0.1:6353;
    }
    }
  • 服务器读取 ip 是使用 头部信息的 ip, 比如: gin

    ```go
    ip := ctx.Request.Header.Get(“X-Forwarded-For”)
    // ip := ctx.ClientIP() 不要使用这个 api 获取 ip