侧边栏壁纸
  • 累计撰写 8 篇文章
  • 累计创建 20 个标签
  • 累计收到 3 条评论

目 录CONTENT

文章目录

Nginx反向代理halo博客并实现https访问

LengJun
2022-02-27 / 0 评论 / 4 点赞 / 2,040 阅读 / 12,661 字
温馨提示:
本文最后更新于 2022-03-18,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

一、需要准备什么

  • 一个正常访问的VPS;
  • OS:CentOS 7/8;
  • 本文以root用户安装halo;
  • 一个域名,并已解析到服务器的ip;
  • CentOS 8需要在/etc/yum.repos.d中更新一下源,使用vault.centos.org代替mirror.centos.org
sudo sed -i -e "s|mirrorlist=|#mirrorlist=|g" /etc/yum.repos.d/CentOS-*
sudo sed -i -e "s|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g" /etc/yum.repos.d/CentOS-*
  • 关闭SELinux,否则nginx无法代理Halo,显示502 Bad Gateway
setsebool -P httpd_can_network_connect 1 && setenforce 0

二、配置SSL证书

  • 安装Certbot
yum install -y python36 && pip3 install certbot 

运行这条命令后,显示 Successfully installed xxxx, xxxx, xxxx (各种软件包名字)表示成功

  • 停止防火墙 (在CentOS7版本以上,默认开启防火墙,不关闭防火墙将无法申请证书)
systemctl stop firewalld && systemctl disable firewalld

运行这条命令后,显示
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
(表示成功)
  • 申请SSL证书
certbot certonly --standalone --agree-tos -n -d www.●●●●●● -d ●●●●●● -m ▲▲▲@▲▲▲.▲▲▲

第一个-d加一个带www的域名,第二个-d加一个不带www的域名,-m后面加你的电子邮箱。注意前后要带空格。

例子:(域名:www.10086.website,邮箱:10086@protonmail.com)

certbot certonly --standalone --agree-tos -n -d www.10086.website -d 10086.website -m 10086@protonmail.com

运行这条命令后,如果显示:

IMPORTANT NOTES:
Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/www.10086.website/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/www.10086.website/privkey.pem
Your cert will expire on 2020-06-04. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt:  https://letsencrypt.org/donate
Donating to EFF:                    https://eff.org

(表示成功)

注意:这一步比较容易出错,常见的问题有:

  1. 其它代理占用了80,443端口。解决方法:停止其它代理软件,或重装VPS。
  2. 没有正确配置域名解析。解决方法:ping一下域名,看看能不能正确解析到IP。
  3. 没有关闭防火墙。解决方法:关闭防火墙。
  • 配置证书自动更新
echo "0 0 1 */2 * service nginx stop; certbot renew; service nginx start;" | crontab

我们申请的证书只有三个月期限,上面的命令表示每隔两个月,证书就自动续命一次,从而保证可以一直用下去。运行这条命令后,如果没有任何信息输出,就表示成功。

可以查看crontab定时任务

 crontab -l

三、安装Nginx

yum install -y nginx

Centos如果没有nginx源需要手动添加

vi /etc/yum.repos.d/nginx.repo
在文件中写入以下内容:
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

四、上传配置文件&运行

  • Nginx的配置文件存储在
cd /etc/nginx/conf.d
  • 转到conf.d目录,编辑default.conf文件
server {
  ### 1:标注“●”的地方填写域名,注意这里的域名带www,例如 www.10086.website
  ### 一共有三处需要填,都以“●”标出,“●”应该被删除,并被域名代替
  server_name ●●●●●●●●●●●●;

  listen 80;
  listen [::]:80;
  rewrite ^(.*) https://$server_name$1 permanent;
  autoindex off;
  server_tokens off;
  }

  server {
  ssl_certificate /etc/letsencrypt/live/●●●●●●●●●●●●/fullchain.pem;

  ssl_certificate_key /etc/letsencrypt/live/●●●●●●●●●●●●/privkey.pem;

  location / 
  {
      proxy_pass http://127.0.0.1:8090;
      proxy_redirect off;
      proxy_http_version 1.1;
      proxy_set_header HOST $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      client_max_body_size 1024m;

      sendfile on;
      tcp_nopush on;
      tcp_nodelay on;
      keepalive_requests 25600;
      keepalive_timeout 300 300;
      proxy_buffering off;
      proxy_buffer_size 8k;
  }

  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name $server_name;
  charset utf-8;

  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK;
  ssl_prefer_server_ciphers on;

  ssl_session_cache shared:SSL:60m;
  ssl_session_timeout 1d;
  ssl_session_tickets off;

  ssl_stapling on;
  ssl_stapling_verify on;
  resolver 8.8.8.8 8.8.4.4 valid=300s;
  resolver_timeout 10s;

  add_header X-Frame-Options DENY;
  add_header X-XSS-Protection "1; mode=block";
  add_header X-Content-Type-Options nosniff;
  add_header Strict-Transport-Security max-age=31536000 always;
  autoindex off;
  server_tokens off;

  location ~ .*\.(js|jpg|JPG|jpeg|JPEG|css|bmp|gif|GIF|png|mp4|mp3|ico)$
  {
    proxy_pass http://127.0.0.1:8090;
  }
}
  • 开启GZIP,日志等功能
vi /etc/nginx/nginx.conf

需注销两个server块的代码,在代码行最前面加#即可。

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    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;
#    tcp_nodelay         on;
#    keepalive_timeout   65;
#    types_hash_max_size 2048;

#    include             /etc/nginx/mime.types;
#    default_type        application/octet-stream;
#
    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;
      gzip  on;
  gzip_min_length  1k;
  gzip_buffers     4 16k;
  gzip_http_version 1.1;
  gzip_comp_level 5;
  gzip_types       text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/javascript application/json;
  gzip_disable "MSIE [1-6]\.";
  gzip_vary on;
#
#    server {
#        listen       80 default_server;
#        listen       [::]:80 default_server;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        location / {
#        }
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }
#
# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2 default_server;
#        listen       [::]:443 ssl http2 default_server;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers PROFILE=SYSTEM;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        location / {
#        }
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }
#
}

  • 保存退出,验证一下Nginx配置是否正确,输入:
nginx -t

运行这条命令后显示
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
说明配置没有问题
  • 运行Nginx
Nginx开机自启:
systemctl start nginx
systemctl enable nginx

启动Nginx: service nginx start
重启Nginx: service nginx restart
查看Nginx状态:service nginx status
停止Nginx:service nginx stop

五、安装 Halo

  • 安装 Java 运行环境
yum install java-11-openjdk -y

检测是否安装成功

java -version

如果输出以下类似内容即代表成功
openjdk version "11.0.10" 2021-01-19 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.10+9-LTS)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.10+9-LTS, mixed mode, sharing)
  • 下载配置文件到 ~/.halo目录。在 Halo 运行的时候会在系统当前用户目录下产生一个 .halo 的文件夹,绝对路径为 ~/.halo
curl -o ~/.halo/application.yaml --create-dirs https://dl.halo.run/config/application-template.yaml
  • 下载Halo安装包
mkdir /usr/local/src/halo && cd /usr/local/src/halo && yum -y install wget && wget https://dl.halo.run/release/halo-1.4.17.jar -O halo.jar
  • 启动测试
java -jar halo.jar

出现以下日志输出,则代表启动成功
run.halo.app.listener.StartedListener    : Halo started at         https://127.0.0.1:8090
run.halo.app.listener.StartedListener    : Halo admin started at   https://127.0.0.1:8090/admin
run.halo.app.listener.StartedListener    : Halo has started successfully!

这时在浏览器输入域名测试能否进行博客初始化。

如果无法正常打开博客,可以运行以下命令查看日志

查看Nginx连接日志:tail -f /var/log/nginx/access.log

六、Halo进阶配置

以上的启动仅仅为测试 Halo 是否可以正常运行,如果我们关闭 ssh 连接,Halo 也将被关闭。你可使用 CTRL+C 停止运行测试进程。要想一直处于运行状态,请继续看下面的教程。

  • 下载 Halo 官方的 halo.service 模板
wget https://dl.halo.run/config/halo.service -O /etc/systemd/system/halo.service
  • 修改 halo.service
vi /etc/systemd/system/halo.service
  • 打开之后我们可以看到
[Unit]
Description=Halo Service
Documentation=https://halo.run
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=USER
ExecStart=/usr/bin/java -server -Xms256m -Xmx256m -jar YOUR_JAR_PATH
ExecStop=/bin/kill -s QUIT $MAINPID
Restart=always
StandOutput=syslog

StandError=inherit

[Install]
WantedBy=multi-user.target
  1. YOUR_JAR_PATH:Halo 安装包的绝对路径,需要修改,比如改成/usr/local/src/halo/halo.jar
  2. USER:运行 Halo 的系统用户,修改为你创建的用户名称即可。如果你是以root用户运行Halo请删除 User=USER
  3. 请确保 /usr/bin/java是正确无误的。建议将 ExecStart 中的命令复制出来运行一下,保证命令有效。
  • 重新加载 systemd
systemctl daemon-reload
  • Halo常用命令
启动 Halo:service halo start
Halo开机自启:systemctl enable halo
重启 Halo:service halo restart
停止 Halo:service halo stop
查看 Halo 的运行状态: sudo service halo status
查看服务日志检查启动状态:journalctl -n 20 -u halo

七、halo 升级

升级前请确保主题已适配新版halo

停止halo: service halo stop
备份数据:cp -r ~/.halo ~/.halo.bak
重命名(备份)旧运行包:mv /usr/local/src/halo/halo.jar /usr/local/src/halo/halo.jar.bak
下载最新版本的运行包:cd /usr/local/src/halo/ && wget https://dl.halo.run/release/halo-1.4.17.jar -O halo.jar
启动测试:java -jar halo.jar
重启:service halo restart

八、加固服务器

  • 配置防火墙
    如果VPS上没有其它服务,建议打开防火墙。服务器对外只暴露80,443,SSH端口。

    systemctl start firewalld && systemctl enable firewalld   #开启防火墙
    firewall-cmd --add-service=http --permanent               #永久开放http服务
    firewall-cmd --add-service=https --permanent              #永久开放https服务
    firewall-cmd --add-service=ssh --permanent                #永久开放ssh服务(默认开启)
    firewall-cmd --reload                                     #更新防火墙规则 
    
  • 禁止root远程登录

    新建普通权限的用户:useradd your_new_account_name
    设置用户密码:passwd your_new_account_name
    给普通用户加sudo权限:chmod 777 /etc/sudoers && vi /etc/sudoers
    

    找到

    root  ALL=(ALL)    ALL
    
    在“root ALL=(ALL) ALL”这一行下面,再加入一行:
    your_new_account_name  ALL=(ALL)    ALL
    
    :wq保存退出!
    chmod 444 /etc/sudoers
    

    使用新用户登入VPS

    切换至root用户:sudo su
    

    禁止ROOT远程SSH登录

    vi /etc/ssh/sshd_config
    
    把
    PermitRootLogin yes
    改为
    PermitRootLogin no
    
    重启sshd服务
    service sshd restart
    
  • 开启密钥登录

    • 使用ssh-keygen生成RSA秘钥对
      假设使用新用户demo登入VPS, 运行命令:ssh-keygen -t rsa,之后一直按回车。

      Generating public/private rsa key pair.
      Enter file in which to save the key (/home/demo/.ssh/id_rsa):
      Enter passphrase (empty for no passphrase):
      Enter same passphrase again:
      Your identification has been saved in /home/demo/.ssh/id_rsa.
      Your public key has been saved in /home/demo/.ssh/id_rsa.pub.
      The key fingerprint is:
      SHA256:Kc0xeDMJp9Ki0f5sZU1sqdq18lc6MDcClchDuF1oxnM demo@test- 
      server
      The key's randomart image is:
      +---[RSA 2048]----+
      | .=oo . |
      | . ..=XoE. |
      | . + +=B*= |
      | + o.+o@ |
      | . . . S.o |
      | o * .+.o . |
      | = o .= + |
      | . o + |
      | .. . |
      +----[SHA256]-----+
      

      可以看到ssh-keygen在/home/demo/.ssh/目录下生成了两个文件:id_rsa和id_rsa.pub,其中id_rsa为私钥,id_rsa.pub为公钥。

    • 把公钥的内容追加到.ssh目录下的authorized_keys文件中
      这里分为两种情况:
      1、authorized_keys文件存在,里面已存在其他用户登录的公钥,那么只需要把生成的公钥的内容追加到authorized_keys。
      cat id_rsa.pub >> authorized_keys

      2、如果authorized_keys不存在,则可以直接把id_rsa.pub重命名为authorized_keys。
      mv id_rsa.pub authorized_keys

    • 修改authorized_keys访问权限
      将目录.ssh权限设置为700,公钥文件authorized_keys设置为644

      chmod 700 ../.ssh/
      chmod 644 authorized_keys
      
    • 修改ssh配置

      切换至root用户:sudo su
      
      vi /etc/ssh/sshd_config
      
      PubkeyAuthentication yes
      # The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
      # but this is overridden so installations will only check .ssh/authorized_keys
      AuthorizedKeysFile      .ssh/authorized_keys
      

      这里有一点很重要,在你配置密钥登录成功之前,不要把PasswordAuthentication 设置no,否则你密钥登录不了,然后又禁止密码登录,就悲剧了。
      在密钥登录设置成功之后,可以将PasswordAuthentication 设置为no,禁用密码登录,比较安全。

      设置完成后重启ssh服务

      systemctl restart sshd.service
      
    • 使用私钥登录
      把生成的私钥id_rsa下载到客户端,客户端登录时选择使用秘钥登录,并且选择与服务器配对的私钥,也就是下载到客户端的私钥id_rsa。

  • 使用Fail2ban防止SSH爆破

    Fail2Ban是一个入侵检测系统框架,它可以保护电脑服务器免受蛮力攻击。
    Fail2ban 跟 DenyHosts是类似的工具,可以阻挡有人恶意以字典暴力破解密码,通常应用于有开启 sshd、telnetd跟ftpd的主机上。

    • 安装fail2ban

      # CentOS内置源并未包含fail2ban,须要先安装epel源
      yum -y install epel-release
      #安装fial2ban
      yum -y install fail2ban
      

      安装成功后fail2ban配置文件位于/etc/fail2ban

    • 新建jail.local来覆盖fail2ban的一些默认规则,文件放在与jail.conf的同一目录就行。

      # 新建文件
      cd /etc/fail2ban
      touch jail.local
      # 编辑配置内容
      vi jail.local
      
      # 默认配置
      [DEFAULT]
      # IP白名单,白名单中的IP不会屏蔽,可填写多个以(,)分隔
      ignoreip=127.0.0.1/8
      # 屏蔽时间,单位为秒(s)
      bantime=3600
      # 时间范围
      findtime=600
      # 最大次数
      maxretry=3
      
      # 新建规则名称
      [sshd]
      # 是否启动该规则
      enabled=true
      # 规则名称,必须填写位于filter.d目录里面的规则,sshd是fail2ban内置规则
      filter=sshd
      # 对应的端口
      port=22
      # 须要监视的日志路径
      logpath=/var/log/secure
      

      上述配置内容表示:若是同一个IP,在10分钟内,若是连续超过3次错误,则将他IP ban了。

    • Fail2Ban默认使用iptables,要使Fail2Ban能够使用firewalld,请使用以下命令将00-firewalld.conf复制到00-firewalld.local

      mv /etc/fail2ban/jail.d/00-firewalld.conf /etc/fail2ban/jail.d/00-firewalld.local
      
    • 启动fail2ban

      systemctl start fail2ban && systemctl enable fail2ban
      
    • 验证fail2ban是否生效

      执行以下命令以检查特定监控的状态:
      fail2ban-client status sshd
      
      你将获得类似的输出如下:
      Status for the jail: sshd
      |- Filter
      |  |- Currently failed:	0
      |  |- Total failed:	3
      |  `- Journal matches:	_SYSTEMD_UNIT=sshd.service + _COMM=sshd
      `- Actions
      |- Currently banned:	1
      |- Total banned:	1
      `- Banned IP list:	69.55.54.65 
      
      执行以下命令以显示由Fail2Ban生成的Firewalld Rich-Rules:
      firewall-cmd --list-rich-rules
      
      你将获得类似的输出如下:
      rule family="ipv4" source address="69.55.54.65" port port="22" protocol="tcp" reject type="icmp-port-unreachable"
      表明fail2ban正在积极防护
      
    • 关于运行命令firewall-cmd --reload会清空防护规则的问题,建议运行这条命令后重启fail2ban,systemctl restart fail2ban

4

评论区