Lework Study hard, improve every day.

学习周报「2024」12月

2024-12-01
lework
本文 2988 字,阅读全文约需 9 分钟

以每周一个节点,记录知识点。

2024-12-09~15

不重建 Docker 容器的情况下修改端口绑定

在 Docker 中,我们可以通过 docker run -p 或者 docker run -P 来将 container 的端口映射到宿主机的端口。但是如果我们想修改 container 的端口映射,通常的做法是删除 container,然后重新创建一个新的 container。但是这样做会导致 container 的数据丢失,如果我们不想丢失数据,可以通过修改 container 的配置文件来实现。

例如我们想将 container 的 80 端口映射到 8080 端口,可以按照下列方式操作:

  1. 查看 container 的 id
    docker inspect --format="{{.Id}}" container_name
    
  2. 关闭容器和 docker 服务
    docker stop container_name
    systemctl stop docker
    
  3. 修改 container 的配置文件 修改 /var/lib/docker/containers/{{container_id}}/hostconfig.json 文件中的 PortBindings 配置,将 80 端口映射到 8080 端口。
    ...
    "PortBindings": {
      "3000/tcp": [
     {
       "HostIp": "",
       "HostPort": "3001"
     }
      ],
      "80/tcp": [
     {
       "HostIp": "",
       "HostPort": "8080"
     }
      ]
    }
    ...
    

    修改 /var/lib/docker/containers/{{container_id}}/config.v2.json 文件中的 ExposedPorts, Ports 配置

    ...
    "Config": {
      "ExposedPorts": {
     "3000/tcp": {},
     "80/tcp": {}
      }
    },
    ...
    "NetworkSettings": {
      "Ports": {
     "3000/tcp": [
       {
         "HostIp": "0.0.0.0",
         "HostPort": "3001"
       }
     ],
     "80/tcp": [
       {
         "HostIp": "0.0.0.0",
         "HostPort": "8080"
       }
     ]
      }
    }
    ...
    
  4. 重启 Docker 服务
    systemctl restart docker
    
  5. 启动 container
    docker start container_name
    
  6. 查看 container 的端口绑定
    docker port container_name
    

但是上面的方式需要重启 Docker container,如果不想重启 container,可以通过临时修改 iptables 规则来实现。

HOST_PORT=8080
CONTAINER_PORT=80
CONTAINER_IP=$(docker inspect --format="{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}" container_name)

# 在 nat 表中添加 DNAT 规则, 将宿主机的 HOST_PORT 端口映射到容器的 CONTAINER_PORT 端口
iptables -t nat -I DOCKER 1 -p tcp --dport ${HOST_PORT} -j DNAT --to-destination ${CONTAINER_IP}:${CONTAINER_PORT}

# 在 nat 表中添加 MASQUERADE 规则, 使容器可以访问外部网络
iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --source ${CONTAINER_IP} --destination ${CONTAINER_IP} --dport ${CONTAINER_PORT}

# 在 filter 表中添加 ACCEPT 规则, 允许外部访问容器的 CONTAINER_PORT 端口
iptables -A DOCKER -j ACCEPT -p tcp --destination ${CONTAINER_IP} --dport ${CONTAINER_PORT}

注意: 上面的方式只能在 Docker container 启动后才能生效,如果 container 重启,需要重新执行上面的命令。宿主机重启后,上面的规则会失效,需要重新执行上面的命令。

2024-12-23~29

非root用户监听特权端口方案

特权端口是指1~1023之间的端口,这些区间范围端口通常需要管理员权限才能监听。非管理员权限只能监控特权端口(1024以上的端口)。

方案1: 使用内核参数

举例:用一个普通用户监控80端口

  1. 使用root添加内核参数,值是我们需要使用普通用户所监听的端口
    # sysctl -w net.ipv4.ip_unprivileged_port_start=80
    
  2. 切换到普通用户并开启监听端口
    # su - zhang3
    [zhang3@c1 ~]$ python3 -m http.server 80
    Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
    

方案2:使用setcap命令添加权限

为程序赋予 CAP_NET_BIND_SERVICE 权限,即使服务程序运行在非root帐户下,也能够 binding 到低位端口。以Nginx为例:

# setcap 'cap_net_bind_service=+eip' /usr/sbin/nginx

此时就可以使用普通用户来运行nginx,即使是监控1024以下的端口。

假如哪一天我想将这权限进行回收,使用以下命令来实现:

# setcap -r /usr/sbin/nginx

方案3: 使用 authbind工具

  1. 为Linux系统安装 authbind
    # wget https://s3.amazonaws.com/aaronsilber/public/authbind-2.1.1-0.1.x86_64.rpm
    # rpm -vih uthbind-2.1.1-0.1.x86_64.rpm
    Verifying...                          ################################# [100%]
    准备中...                          ################################# [100%]
    正在升级/安装...
    1:authbind-2.1.1-0.1               ################################# [100%]
    Debian/Ubuntu
    # apt install authbind
    
  2. 分配特定端口
    # touch /etc/authbind/byport/80
    # chown zhang3 /etc/authbind/byport/80
    # chmod 500 /etc/authbind/byport/80
    
  3. 启动端口
    # su - zhang3
    $ authbind --deep python3 -m http.server 80
    $ ps -ef |grep python3
    zhang3    114803  114741  2 23:47 pts/1    00:00:00 python3 -m http.server 80
    
  • https://vqiu.cn/nonroot-user-listening-on-privilege-ports/
原文地址 https://lework.github.io/2024/12/01/Dec/

Similar Posts

Comments