前言

部署一个网页本身并没有太大难度,租个服务器用默认密码ssh登入root装上Nginx把网页复制到/var/www里然后改一下Nginx的设置,再去Cloudflare把域名解析到你的IP地址,基本就搞定了。问题在于这么做过不了多久你就会发现服务器密码已经被穷举攻破,然后你就变成了肉鸡用于ddos。即使你手动改了个很复杂的密码,也会发现你命令行用起来非常卡,因为你服务器在后台拒绝大量的错误密码登录。因此,为了在这个险恶的互联网环境下生存下去,必须学会如何保护自己的服务器。

服务器安全设置

开服后第一件要做的事就是提升安全性。其实你部署完网页再做也行,但这一段每一项操作出错都有可能让你再也登录不了服务器,只能重装。为了少折腾,还是建议最开始就把这些危险操作都搞定。

修改ssh端口并配置防火墙

第一步我们把默认的ssh端口给改掉,并直接屏蔽22端口的访问。首先打开全局ssh配置文件sudo nano /etc/ssh/sshd_configroot账户可以不用sudo,找到Port 22这一行,把它改成任意与其他服务不冲突的端口,例如Port 1234,按Ctrl+X保存并退出。接着配置ufw防火墙,用sudo ufw allow 1234/tcp添加一个允许1234端口TCP连接的规则。为了防止输入错误导致再也连不上服务器,建议再临时添加一个sudo ufw allow 22/tcp,让当前的远程连接在激活防火墙后还能不断线。

确保ssh端口和防火墙都配置正确后,先用sudo systemctl restart ssh重启ssh服务,这时可以再开一个控制台,用ssh -p 1234 root@your-server-ip-address连接服务器,如果能连上说明ssh配置是正确的。再在任意一个控制台里输入sudo ufw enable激活防火墙,如果新的连接没中断,说明防火墙配置也没问题。不放心可以再开个控制台测试一下。之后就可以把临时的22端口规则删掉了sudo ufw delete allow 22/tcp,这样那些对22端口的穷举爆破就会直接被拦住,不会影响服务器性能了。

创建账户并赋予sudo权限

直接使用root操作服务器是非常危险的行为,容易出现经典的rm -rf不慎删掉整个根目录的失误,因此,我们最好创建一个新账户,并赋予sudo的权限,这样可以避免一些操作失误干掉整个系统,多人使用服务器还能分别记录每个人各自的操作。我们用sudo adduser abc创建一个叫abc的用户,跟着提示输入密码等信息,然后将该用户添加进sudo用户组sudo usermod -aG sudo abc。接着开个新的控制台,用ssh -p 1234 abc@your-server-ip-address登入服务器,然后看看sudo命令是否能用,如果一切正常,可以去ssh设置里禁止直接用root登录,进一步提高安全性。找到/etc/ssh/sshd_config里的PermitRootLogin yes,改成PermitRootLogin no,用sudo systemctl restart ssh重启服务。以后所有root级操作都用新用户的sudo来提权运行,如果真的有什么需要用root用户的操作,可以用su root切换到root。

设置仅允许密钥对登录

即使改掉了ssh的端口号,如果攻击者真的想要爆破你的服务器,他们还可以直接扫描你的所有端口找到哪个用于ssh。禁用root登录可以有效防止陌生人找到正确的用户名穷举出你的密码,但是如果用上了社工手段,你的用户名很有可能能被猜出来,于是你的服务器还是有一定的危险。这里最安全的手段是只允许服务器使用密钥登录,这样除非你的私钥泄漏了,不然仅有你这台设备能登录。

我们先在本地的控制台里,用ssh-keygen -t RSA -b 4096 -C 'comments'创建一个私钥公钥对,comments是备注,你可以改成自己当前电脑的信息。保存位置使用默认的就行,passphrase是解锁这个私钥的密码,设置一个你保证能记住的,最好把passphrase记在纸上。然后去刚才保存的位置,Windows通常在%USERPROFILE%/.ssh/,Ubuntu在~/.ssh/,里面能看到一个id_rsa文件和一个id_rsa.pub文件,没有后缀名的是你的私钥,不要让其他任何人知道。id_rsa.pub是公钥,把它发给别人,你用私钥加密的信息他们可以用公钥来解密。

本地生成了私钥公钥对后,先照常用密码登录服务器,把你的公钥添加到服务器的信任列表中,用nano ~/.ssh/authorized_keys创建一个文件,把本地id_rsa.pub里的内容完整地复制进去,Ctrl+X保存并退出。再打开/etc/ssh/sshd_config,把下面几个验证方式都改成no,只保留PubkeyAuthentication yes

PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
PubkeyAuthentication yes

最后重启ssh服务,你也可以先不关闭当前的连接,再开一个控制台来测试连接。同样使用ssh -p 1234 abc@your-server-ip-address,系统会自动使用你个人文件夹下~/.ssh/id_rsa来与服务器配对,输入设置的passphrase,就能登录了。

如果你有多台设备要登录到同一账号,最正确的操作是每台设备都生成自己的私钥公钥对,把新的公钥先发给第一台设备,再把新设备的公钥加到服务器。还有个简单的操作是直接把第一台设备的私钥复制到其他设备,服务器中只添加这一个公钥。虽然很不正规,也不符合私钥公钥本身的意义(可以看作是唯一的设备身份认证),但对于个人用服务器也足够安全了,同一个私钥多个设备备份还可以防止丢失。

无论如何,强烈建议在安全的地方(例如移动硬盘或能信任的网盘)保存一份私钥,防止你电脑出现意外后再也登不上服务器。

一些密钥相关操作

创建一对RSA加密的公私钥对:ssh-keygen -t RSA -b 4096 -C 'comments'
修改或添加私钥passphrase:ssh-keygen -p -f ~/.ssh/id_rsa
修改或添加私钥comment:ssh-keygen -c -f ~/.ssh/id_rsa
公钥comment直接用文本编辑器打开在末尾修改即可。
将私钥添加进本地缓存,以后使用不需要输入passphrase:ssh-add ~/.ssh/id_rsa
查看当前缓存了哪些私钥:ssh-add -l
移除一个缓存的私钥:ssh-add -d ~/.ssh/id_rsa

部署网页服务器

加强了服务器安全后就可以来正式部署网页了。Nginx是非常适合个人网站的HTTP服务器,性能强,使用简单,网上还能找到大量的教程,我参考的是这个网站

安装Nginx

首先用apt安装Nginx。

sudo apt update
sudo apt install nginx

然后把HTTP和HTTPS的端口添加进防火墙:sudo ufw allow 'Nginx Full'
这时候可以在浏览器打开http://your-server-ip-address,如果能看到一个Welcome to nginx的页面那说明安装成功了。

安装MySQL或任意数据库

除非是非常小的纯静态网页,不然大多数网页都会使用一个数据库来存储网页里的数据。MySQL是曾经十分流行的一个免费开源数据库,其被甲骨文收购后,原作者团队基于MySQL分支开发了继续保持免费开源的MariaDB,二者用起来没什么区别。

安装MySQL可以直接用apt:sudo apt install mysql-server,然后输入sudo mysql_secure_installation来执行一些安全措施。开始时会问你要不要使用强密码,可以根据你需求选择密码强度要求等级,不建议选STRONG,有点极端了,MEDIUM是比较合适的,要求有数字、大小写字母和特殊符号。接着会让你设置一个数据库root用户的密码,这里的root服务器root不是同一个,注意不要混淆。后面的设置基本上一路确认就行了,会自动禁用一些不安全的设置,例如禁止远程登录数据库。流程跑完后可以用sudo mysql测试能否进入数据库管理,输入exit或者按Ctrl+D即可退出。可以注意到这里并没有要求验证任何密码,这是因为MySQL认为你都有sudo权限了,那肯定应该能随意处理数据库。但这也是个不太安全的行为,我们需要两个操作来让数据库更安全:要求root也要使用密码,以及创建仅能操作特定database的用户。

MySQL设置root使用密码登录

首先还是用sudo mysql进入数据库,注意后面的每个命令都要结尾加分号才会执行。可以输入SELECT user, host, plugin FROM mysql.user WHERE user = 'root';查看当前所有用户的登录验证方式,能看到rootauth_socket,即只要是服务器的root就可以直接登录。输入如下命令将root的登录方式改为仅密码:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password;
FLUSH PRIVILEGES;

为了防止出问题,跟之前一样,可以开个新控制台,使用mysql -u root -p来使用密码登录root,注意以后登录数据库不再需要sudo提权。如果出现了问题,还可以在之前的连接中输入下面的命令来重设密码:

# 仅当用之前设置的密码无法登录时
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码';
FLUSH PRIVILEGES;

创建MySQL用户并给予权限

部署网站时通常做法是为每个服务创建一个单独的数据库账号,仅给予每个账号访问对应数据库的权限。以数据库名data1,对应用户user1为例,先用root登入MySQL,然后进行如下操作:

CREATE DATABASE data1;
CREATE USER 'user1'@'localhost' IDENTIFIED WITH mysql_native_password BY '用户密码';
GRANT ALL ON data1.* TO 'user1'@'localhost';
FLUSH PRIVILEGES;

这样就创建了一个新用户user1并给予了他完全控制data1的权限,可以用mysql -u user1 -p来登入。这里该用户的域是localhost,即本地用户。如果之后想要允许远程连接数据库,这里要把localhost改成一个百分号'%'。

MySQL数据库备份

这里顺便讲一下数据库备份。理论上使用MySQL的root用户可以执行所有操作,但是本着root能不用就不用的原则,我们可以再创建一个专门用于备份data1的用户。注意user1虽然能操作data1,但其并不能导出备份data1,因为缺少读取总数据的一些权限。这里我们单独为data1的备份创建一个data1_backup用户:

CREATE USER 'data1_backup'@'localhost' IDENTIFIED WITH mysql_native_password BY '用户密码';
GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON `data1`.* TO 'data1_backup'@'localhost';
GRANT PROCESS, RELOAD, REPLICATION CLIENT ON *.* TO 'data1_backup'@'localhost';
FLUSH PRIVILEGES;

以后每次需要备份时,输入mysqldump -u data1_backup -p data1 > backup_filename.sql即可。

安装PHP

根据你想要部署的网页框架安装所需版本的PHP:sudo apt install php-fpm php-mysql php-mbstring,mbstring库是用来正确处理非ASCII字符的。

配置Nginx

网页服务器必备的模块都安装好后我们就可以用Nginx来部署我们的网站了。首先我们在Nginx的网站存储位置创建一个项目文件夹sudo mkdir /var/www/你的域名,如果没有域名随便取个名字就行。注意/var/www/这个文件夹需要提权才能写入,但我们不能给网页服务器sudo权限,所以我们把这个项目文件夹所有权转给当前用户sudo chown -R $USER:$USER /var/www/你的域名。你可以在这个项目文件夹下先添加一个index.html文件,随便打几个字,用于之后的测试。接着我们创建一个我们网站的配置文件sudo nano /etc/nginx/sites-available/你的域名,里面先输入如下内容并保存:

server {
    listen 80;
    server_name 你的域名 www.你的域名;
    root /var/www/你的域名;

    index index.html index.htm index.php;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
     }

    location ~ /\.ht {
        deny all;
    }

}

其中的php版本根据你安装的来修改。这个最基本的配置文件设置了网站入口和PHP解析器,但仅支持HTTP连接,如今随着浏览器(特别是Google Chrome)安全标准的提高,一个网站如果不使用HTTPS协议加密,很有可能会被直接禁止访问。不过我们先把后面的网站服务器基本设置搞定再折腾SSL证书。

下一步是把我们网站的配置文件作为当前使用的配置文件sudo ln -s /etc/nginx/sites-available/你的域名 /etc/nginx/sites-enabled/,同时把默认的删除sudo unlink /etc/nginx/sites-enabled/default。然后让Nginx检查你的配置文件是否合法sudo nginx -t,并重新加载sudo systemctl reload nginx。现在再访问
http://your-server-ip-address,应该可以看到你在index.html里随机打的字了。

为了测试PHP是否正确安装,你还可以在项目文件夹中创建一个info.php文件,输入:

<?php
phpinfo();

然后浏览器打开http://your-server-ip-address/info.php查看是否显示了调试信息。

域名与SSL设置

为了使用HTTPS协议,我们需要给自己的网站配置一个SSL证书。参考如下文章,我们用免费的Certbot来给我们的网站签发一个证书。前提条件是你已购买一个域名,并用Cloudflare或相似DNS服务商把该域名指向了你的服务器IP地址,要同时设置xxxx.comwww.xxxx.com

先安装需要的程序sudo apt install certbot python3-certbot-nginx,然后输入sudo certbot --nginx -d 你的域名 -d www.你的域名来签发证书,第一次使用会要求你填写邮箱地址。然后Certbot会自动在你网站的Nginx配置文件里添加一些条目。可以打开确认一下是否主配置里的监听端口改成了listen 443;,还增加了一些包含certbot注释的行,最后还把80端口导向了404错误。

现在你就可以用https://your-server-ip-address来访问自己的网站了,能看到浏览器非常开心地给了你安全的标志。Certbot签发的SSL证书有效期为90天,到期会自动更新,一般不再需要去关心了。

最后的细节

根据网站框架的不同还有一些小细节需要处理一下,如果你像我一样使用GitHub来同步代码,同时网站有上传附件的功能,需要在Nginx的网站配置文件里设置一个最大附件体积,还要禁止访客访问.git文件夹,因为其中很可能存储了例如你的姓名和邮箱等信息,最好不要让攻击者知道。

server {
        root /var/www/你的域名;
        # 一些其他配置
        client_max_body_size 100M;

        location ~/\.git {
                deny all;
        }
    # 更多配置
}

(可选)利用Docker部署

Last modification:December 9, 2025
点赞喵,点个赞谢谢喵