为什么nginx用户使用的nginx不能监听80端口?

前段时间在面试的时候,本来面的一切顺利,但是在聊到nginx的时候,面试官突然提问到:"你平时nginx都是用什么用户启动的?",我一愣,猜想肯定有坑,但也只能见招拆招了,"nginx用户",果不其然,面试官立马接下一招:"那你用nginx用户启动nginx,这时候nginx还能监听80端口嘛?"我一愣,就这?按照平时使用nginx的经验,我回答到:"能"。但是面试官一叹气:"再回去多看看吧"。我脑海中模糊的闪过一些系统端口和系统用户的知识,但为时已晚,一结束面试,马上开始查漏补缺。

为什么我会有nginx用户能用80端口的印象?

一下面试,我赶紧打开了虚拟机,一查nginx配置文件:user nginx,没错,配置的是nginx用户,ps -ef|grep nginx一下,认真查看之下,我发现了为什么我会觉得nginx用户能监听80端口了。

bash 复制代码
[root@192 ~]# ps -ef|grep nginx
root       58200       1  0 11月03 ?      00:00:00 nginx: master process /usr/sbin/nginx
nginx      58201   58200  0 11月03 ?      00:00:01 nginx: worker process
nginx      58202   58200  0 11月03 ?      00:00:00 nginx: worker process

nginx的worker进程是用来处理实际的网络请求的,但是配置文件是由master进程读取再来创建worker进程,也就是说我们在配置文件中配置的user nginx实际上是为worker进程设置的 。master进程所属者为执行nginx命令的用户,实际上的端口绑定也是由master进程负责的,但是平时在nginx配置文件设置完后一般喜欢直接用root用户启动nginx,所以平时的把nginx的用户设置为nginx,nginx也能监听80端口的错误印象就是从这里来的。

bash 复制代码
[nginx@192 sbin]$ ./nginx
nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)

事实也确实是这样,用普通用户去执行nginx,就会报权限被拒绝的错误。

为什么80端口不给普通用户监听?

了解了现象之后,就得去了解原理了,为什么在Linux中,nginx用户不能去使用80端口呢?那这就得去了解一下系统用户和系统端口的知识了

用户

Linux中系统分为三种:

  • 超级用户:root,具有一切特权,UID为0
  • 系统用户:系统正常工作所必须的内建用户,为了满足相应的系统进程而建立,不能用来登录,如bin、daemon、adm、lp等,UID一般为1-499
  • 普通用户:为了让使用者能够使用系统资源而建立的,UID为500-60000

1-499的uid是系统自留的,所以当我们创建用户时,如果不使用-u参数指定uid,那么uid是一定大于等于500的

端口

端口的范围:端口号的范围是从0到65535。这些端口号,根据用途可分为三个类别(范围):

  • 系统端口(0 - 1023):这些端口是众所周知的端口,由IANA(互联网数字分配机构,Internet Assigned Numbers Authority)分配给特定服务。
  • 注册端口(1023 - 49151):这些端口被称为用户端口,可用于注册IANA。注册是为了避免端口冲突。
  • 动态端口(49152-65535):动态端口可以分配给服务一段时间,主要由客户端程序使用

系统端口可不是给系统用户用的,事实上系统端口只有超级用户能使用,其他用户边都别来挨。

bash 复制代码
[root@192 App]# useradd test -u100 
[root@192 App]# id test
uid=100(test) gid=1002(test) 组=1002(test)
[root@192 App]# su test
[test@192 App]$ cd nginx-1.24.0/
[test@192 nginx-1.24.0]$ sbin/nginx
nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)

经过测试得知,系统端口只能由超级管理员使用,其他用户就别想用了。

普通用户使用系统端口的方法

一个用户占用这么多端口,其他用户肯定嫉妒的眼红,那有没有什么办法让普通用户也能用上系统端口呢?肯定是有的,而且不只一种。

1.useradd

bash 复制代码
[root@192 App]# useradd t -u0 -o # 把用户id指定位0
[root@192 App]# id t
uid=0(root) gid=0(root) 组=0(root)
[root@192 App]# nginx-1.24.0/sbin/nginx # 忽悠成功

事实上,我们在创建用户的时候,可以用-u参数指定uid,然后使用-o参数指定用户可以使用已被使用的uid,这样就能成功骗过系统,让系统认为这个用户也是超级管理员(虽然就是)。因为Linux系统中判断用户是根据用户uid来判断的,所以Linux中名字不重要,uid才重要。

2.使用s权限

在Linux中,除了rwx权限之外,还有一种特殊权限s,这种权限只对二进制可执行文件有效,如/usr/bin/passwd就加上了suid权限,当一个普通用户在执行这个命令的时候,其实是root用户在执行命令

bash 复制代码
[root@localhost sbin]# file /usr/bin/passwd
/usr/bin/passwd: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=87e17c1d9b2e20d7e8aeab9115074375eec5e8e1, stripped
[root@localhost sbin]# ll /usr/bin/passwd
-rwsr-xr-x. 1 root root 33600 4月   7 2020 /usr/bin/passwd

只有在这里有ELF的才是二进制文件,suid权限对其他文件没有效果

3.setcap

setcap命令是Linux命令,用来设置文件的能力(capabilities)。在Linux系统中,能力是一种比权限模型更细粒度的权限控制机制。通过将root用户的特权分割成不同的能力,每种能力代表一定的特权操作。如:CAP_SYS_MODULE表示能加载内核模块的特权,CAP_SETUID表示用户能够修改用户身份。

  • setcap命令格式
bash 复制代码
setcap [-q] [-n <rootuid>] [-v] { capabilities|-|-r} filename
# capabilities:设置的能力
# 可以使用man setcap来查看更多信息
bash 复制代码
[root@localhost sbin]# setcap 'CAP_NET_BIND_SERVICE=+ep' nginx
[root@localhost sbin]# getcap nginx
nginx = cap_net_bind_service+ep
# 使用getcap查看能力

4.sudo

在Linux中,任何用户都能提权为root,可以使用visudo进行设置,也可以直接对/etc/sudoers文件进行修改

bash 复制代码
# root表示用户名
# 第一个ALL表示适用的主机
# 第二个ALL为提权为什么用户
# 第三个ALL为可以执行什么命令
root    ALL=(ALL)       NOPASSWD: ALL

## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       ALL
相关推荐
C++忠实粉丝26 分钟前
Linux环境基础开发工具使用(2)
linux·运维·服务器
康熙38bdc1 小时前
Linux 环境变量
linux·运维·服务器
存储服务专家StorageExpert1 小时前
DELL SC compellent存储的四种访问方式
运维·服务器·存储维护·emc存储
hakesashou2 小时前
python如何比较字符串
linux·开发语言·python
Ljubim.te2 小时前
Linux基于CentOS学习【进程状态】【进程优先级】【调度与切换】【进程挂起】【进程饥饿】
linux·学习·centos
cooldream20092 小时前
Linux性能调优技巧
linux
大G哥2 小时前
记一次K8S 环境应用nginx stable-alpine 解析内部域名失败排查思路
运维·nginx·云原生·容器·kubernetes
妍妍的宝贝2 小时前
k8s 中微服务之 MetailLB 搭配 ingress-nginx 实现七层负载
nginx·微服务·kubernetes
醉颜凉2 小时前
银河麒麟桌面操作系统修改默认Shell为Bash
运维·服务器·开发语言·bash·kylin·国产化·银河麒麟操作系统
QMCY_jason3 小时前
Ubuntu 安装RUST
linux·ubuntu·rust