一、 准备工作

1.1 修改源: /etc/apt/source.list

deb https://mirror.nju.edu.cn/proxmox/debian/pve bookworm pve-no-subscription
deb https://mirror.nju.edu.cn/debian/ bookworm main contrib non-free
deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription

1.2 修改源: /etc/apt/source.list.d/pve-no-subscription.list

deb https://mirrors.ustc.edu.cn/proxmox/debian/pve bookworm pve-no-subscription

1.3 注释企业版订阅:

/etc/apt/source.list.d/pve-enterprise.list

1.4 更新

apt update && apt dist-upgrade

二、 相关报错

2.1 pve-apt-hook: not found

/bin/sh: 1: /usr/share/proxmox-ve/pve-apt-hook: not found
E: Sub-process /usr/share/proxmox-ve/pve-apt-hook returned an error code (127)
E: Failure running script /usr/share/proxmox-ve/pve-apt-hook

解决:

mkdir -p /usr/share/proxmox-ve
touch /usr/share/proxmox-ve/pve-apt-hook
chmod +x /usr/share/proxmox-ve/pve-apt-hook

2.2 ceph-common Depends

ceph-common : Depends: librbd1 (= 16.2.15-pve1) but 17.2.7-pve2~bpo11+1 is to be installed
Depends: python3-cephfs (= 16.2.15-pve1) but it is not going to be installed
Depends: python3-ceph-argparse (= 16.2.15-pve1) but 17.2.7-pve2~bpo11+1 is to be installed
Depends: python3-ceph-common (= 16.2.15-pve1) but 17.2.7-pve2~bpo11+1 is to be installed
Depends: python3-rados (= 16.2.15-pve1) but it is not going to be installed
Depends: python3-rbd (= 16.2.15-pve1) but it is not going to be installed
Depends: python3-rgw (= 16.2.15-pve1) but it is not going to be installed

原因: 存在不通版本的pve源,或者没有取消企业版pve的源,导致update的时候部分软件包安装报错, 降级相关软件包重新安装 proxmox-ve即可

零、 环境介绍

  • kubernetes v 1.20.0
  • docker v 20.10.24
主机 ip 系统 配置 角色
k8s-master 192.168.100.200 CentOS 7.9 2c4g 40GB Master
k8s-node1 192.168.100.201 CentOS 7.9 2c4g 40GB Work
k8s-node2 192.168.100.202 CentOS 7.9 2c4g 40GB Work

一、 环境配置

1.0 设置主机名

  • 三台服务器都需要配置
    hostnamectl set-hostname <hostname>

1.1 禁止 SWAP 分区

  • 三台服务器都需配置
    swapoff -a
    sed -ri 's/.*swap.*/#&/' /etc/fstab

1.2 关闭防火墙

  • 三台服务器都需配置
    systemctl stop firewalld iptables
    systemctl disable firewalld iptables

1.3 关闭 SeLinux

  • 三台服务器都需配置
    sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
    setenforce 0

1.4 配置主机名

  • 三台服务器都需配置
    cat >> /etc/hosts << EOF
    192.168.100.200 k8s-master
    192.168.100.201 k8s-node1
    192.168.100.202 k8s-node2
    EOF

1.5 配置时间同步

  • 三台服务器都需配置
    systemctl enable chronyd --now

1.6 配置网桥转发

  • 三台服务器都需配置

    cat >> /etc/sysctl.d/k8s.conf << EOF
    net.ipv4.ip_forward = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.bridge.bridge-nf-call-ip6tables = 1
    EOF

二、 安装 docker (所有节点)

  • 配置 docker 阿里源

    yum install -y yum-utils

    yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  • 安装 docker-ce、 docker-ce-cli
    yum install yum install docker-ce-19.03.15 docker-ce-cli-19.03.15

  • 配置 docker 自启
    systemctl enable docker --now
    systemcyl enable containerd

  • 配置容器镜像加速
    https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

    mkdir -p /etc/docker
    tee /etc/docker/daemon.json <<-'EOF'
    {
    "registry-mirrors": ["https://nbtrfxxy.mirror.aliyuncs.com"],
    "exec-opts": ["native.cgroupdriver=systemd"],
    "log-driver": "json-file",
    "log-opts": {
    "max-size": "100m"
    },
    "storage-driver": "overlay2"
    }
    EOF
    systemctl daemon-reload
    systemctl restart docker

三、 安装 kubelet、kubectl、 kubeadm (所有节点)

  • 配置 kubernetes 阿里源
    cat <<'EOF' > /etc/yum.repos.d/kubernetes.repo
    [kubernetes]
    name=Kubernetes
    baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
    enabled=1
    gpgcheck=0
    repo_gpgcheck=0
    gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
    http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
    EOF
  • 安装 kubelet kubeadm kubectl
    yum install -y kubelet-1.20.0 kubeadm-1.20.0 kubectl-1.20.0 --nogpgcheck

3.1 初始化 Master 节点 (k8s-master)

  • 配置自启
    systemctl enable kubelet --now

  • 导出配置文件
    kubeadm config print init-defaults --kubeconfig ClusterConfiguration > kubeadm.yml

  • 确定镜像
    kubeadm config images list --config kubeadm.yml

  • 下载镜像
    kubeadm config images list --config kubeadm.yml | xargs -I {} docker pull {}

  • 启动

    kubeadm init \
    --apiserver-advertise-address=192.168.100.200 \
    --control-plane-endpoint=k8s-master \
    --image-repository k8s.gcr.io \
    --kubernetes-version v1.20.0 \
    --service-cidr=10.96.0.0/16 \
    --pod-network-cidr=192.168.0.0/16
  • 如下表明安装成功
    图
    图

  • 配置 kubeconfig
    mkdir -p $HOME/.kube
    cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    chown $(id -u):$(id -g) $HOME/.kube/config
    echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /etc/profile

四、 部署Calico(k8s-master)

  • Calico 和 k8s 版本对应关系
    https://docs.tigera.io/archive/v3.21/getting-started/kubernetes/requirements

  • 获取 Calico
    curl https://docs.projectcalico.org/archive/v3.21/manifests/calico.yaml -O

  • 安装 Calico
    kubectl apply -f ./calico.yaml

  • 查看安装

    [root@k8s-master ~]# kubectl get pods -A
    NAMESPACE NAME READY STATUS RESTARTS AGE
    kube-system calico-kube-controllers-5bb48c55fd-pxnbm 1/1 Running 0 2m14s
    kube-system calico-node-4fd75 1/1 Running 0 2m14s
    kube-system coredns-74ff55c5b-k6zz8 1/1 Running 0 6h10m
    kube-system coredns-74ff55c5b-rvsz4 1/1 Running 0 6h10m
    kube-system etcd-k8s-master 1/1 Running 1 6h11m
    kube-system kube-apiserver-k8s-master 1/1 Running 1 6h11m
    kube-system kube-controller-manager-k8s-master 1/1 Running 1 6h11m
    kube-system kube-proxy-zqnwd 1/1 Running 1 6h10m
    kube-system kube-scheduler-k8s-master 1/1 Running 1 6h11m
    [root@k8s-master ~]# kubectl get node
    NAME STATUS ROLES AGE VERSION
    k8s-master Ready control-plane,master 6h11m v1.20.0

五、 node 节点加入 master (在两台node节点上操作)

  • 获取 kubeadm token

    在步骤3.1中初始化 master 的时候生成了 token, 有效期24小时, 如果忘记了初始token, 可以使用一下方法获取

  • 输出当前 token
    kubeadm token list

  • 重新生成 token
    kubeadm token create --print-join-command

  • 获取集群根证书的哈希值

    openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | \
    openssl rsa -pubin -outform der 2>/dev/null | \
    openssl dgst -sha256 -hex | \
    sed 's/^.* //'

5.1 加入集群

  • 在 node1 和 node2 上执行下面命令

    kubeadm join k8s-master:6443 --token 23tt2a.nqn384abbd7rrb8h \
    --discovery-token-ca-cert-hash sha256:7f96b53f61538846515d5905c8073a3919362a893b0463d5bcab7b7b53506af6
    [root@k8s-node1 ~]# kubeadm join k8s-master:6443 --token 23tt2a.nqn384abbd7rrb8h \
    > --discovery-token-ca-cert-hash sha256:7f96b53f61538846515d5905c8073a3919362a893b0463d5bcab7b7b53506af6
    [preflight] Running pre-flight checks
    [preflight] Reading configuration from the cluster...
    [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
    [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
    [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
    [kubelet-start] Starting the kubelet
    [kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

    This node has joined the cluster:
    * Certificate signing request was sent to apiserver and a response was received.
    * The Kubelet was informed of the new secure connection details.

    Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

5.2 验证集群状态

  • k8s-msater 上查看状态
    kubectl get cs

    [root@k8s-master ~]# kubectl get cs
    Warning: v1 ComponentStatus is deprecated in v1.19+
    NAME STATUS MESSAGE ERROR
    controller-manager Unhealthy Get "http://127.0.0.1:10252/healthz": dial tcp 127.0.0.1:10252: connect: connection refused
    scheduler Unhealthy Get "http://127.0.0.1:10251/healthz": dial tcp 127.0.0.1:10251: connect: connection refused
    etcd-0 Healthy {"health":"true"}

    参考解决办法 :https://stackoverflow.com/questions/54608441/kubectl-connectivity-issue
    k8s-master中的 /etc/kubernetes/manifests/kube-controller-manager.yaml/etc/kubernetes/manifests/kube-scheduler.yaml 两个文件中的 --port=0 注释掉 , 然后重启 kubelet 服务

    [root@k8s-master manifests]# kubectl get cs
    Warning: v1 ComponentStatus is deprecated in v1.19+
    NAME STATUS MESSAGE ERROR
    controller-manager Healthy ok
    scheduler Healthy ok
    etcd-0 Healthy {"health":"true"}
    [root@k8s-master manifests]# kubectl cluster-info
    Kubernetes control plane is running at https://k8s-master:6443
    KubeDNS is running at https://k8s-master:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

    To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
    [root@k8s-master manifests]# kubectl get nodes
    NAME STATUS ROLES AGE VERSION
    k8s-master Ready control-plane,master 6h49m v1.20.0
    k8s-node1 Ready <none> 16m v1.20.0
    k8s-node2 Ready <none> 13m v1.20.0

六、 额外

k8s 有太多命令和参数, 为了避免低级错误, 建议使用 bash-completion 补齐命令

  • 安装 bash-completion
    yum install -y bash-completion

  • 配置
    source /usr/share/bash-completion/bash_completion
    echo "source <(kubectl completion bash)" >> /etc/profile

一、 企业业务代码发布方式

传统方式

  1. 物理机或虚拟机
  2. 部署环境负载
  3. 重新部署成本高
  4. 部署后以静态方式展示

容器化方式

  1. 以容器方式部署
  2. 部署简单, 启动快
  3. 一次构建, 到处运行
  4. 随时回复,
  5. 可以同时部署多个环境 (测试, 预发布, 生成化境)

二、 企业业务代码发布逻辑

三、 企业业务代码发布工具及流程图

3.1 工具

工具 作用
git 提交代码
gitlab 存储代码
jenkins 代码编译, 容器构建, 镜像推送
tomcat 运行Java代码
maven 编译业务代码
harbor 存储镜像
docker 镜像构建, 项目部署

前言

假设 Server A 上有一个ipv4的站点: a.ipv4.domain.com
不修改 A 的配置,添加一台支持ipv4和ipv6双栈的公网服务器B;
在 Server B 上通过nginx配置ipv6反向代理ipv4, 实现 ipv6用户访问ipv4资源;

Feature Server A Server B
address ipv4: 100.1.1.1
site: your.domain.com
ipv4: 100.1.1.2
ipv6: 2408:4005:30a:ce00:98b:29f6:6606:xxxx

域名配置

your.domain.com A 记录解析到 100.1.1.1
ipv4.your.domain.com A 记录解析到 100.1.1.1
your.domain.com AAAA 记录解析到 2408:4005:30a:ce00:98b:29f6:6606:xxxx

nginx 配置

这里nginx 只监听ipv6的端口
在 Server B部署 nginx

server {
listen [::]:80;
server_name localhost;

... # 其他配置

location / {
proxy_pass http://ipv4.your.domain.com;
}

先说结论:

  • firewalld无法控制来自本地的流量
  • iptables 可以控制来自本地的流量
  • iptables 默认对ipv4生效,ip6tables对ipv6生效
  • telnet 命令默认会将localhost被解析成::1
  • nmap 会按照/etc/hostslocalhost解析成127.0.0.1
  • ping 在不通的操作系统下localhost的解析效果也不一样, centos中解析为127.0.0.1 debian12 中是 ::1

环境介绍

Feature Server A Server B
OS: CentOS 7.9 Debian 12
ARCH: KVM x86-64 KVM x86-64
IP: 192.168.1.201 192.168.1.28
Docker Remote Port: 2376 2376
Firewalld Version: v0.6.3 v1.3.3

两台服务器默认 iptables为空, firewalld 为空;
默认情况下, iptables 允许放行,firewalld 拒绝;

两台服务器的docker端口均默认监听在tcp6

端口测试脚本:

#!/bin/bash

# Define the port to test
PORT=2376

# Define the addresses to test
ADDRESSES=("localhost" "127.0.0.1" "$(hostname -I | awk '{print $1}')" "::1")

# Function to test telnet connection
test_telnet() {
local address=$1
echo -n "Testing $address:$PORT... "
if timeout 2 telnet $address $PORT 2>/dev/null | grep -q "Connected"; then
echo "Connected"
else
echo "Connection failed"
fi
}
# Loop through the addresses and test each one
for address in "${ADDRESSES[@]}"; do
test_telnet $address
done

测试一

1.1 CentOS:

图片1

1.2 Debian:

图片2

图片3
图片4

结论: firewalld 并不能控制来自本地的流量,即使public的接口里添加了 lo

测试二

两台服务器都添加 iptables 规则后再继续执行脚本测试

iptables -I INPUT -p tcp --dport 2376 -j DROP
图片4
图片4

脚本省略了命令行的输出, 用命令测试一下 telnet localhost 2376
发现两台服务器解析localhost的时候默认解析成 ::1

结论:
iptables 可以阻止来自本地的流量,包括环回接口lo
iptables 默认只处理 ipv4 的流量, ipv6的流量使用 ip6tables
localhost默认会解析成::1

前言

实际应用场景中发现centos7中的firewalld对docker容器监听的端口有时候生效, 有时候不生效, 基于此情况深入研究docker的网络模式

一、 Bridge

bridge 是最常用的默认网络配置选项之一。它为容器创建一个虚拟化的网络环境,通过虚拟网络桥接(Bridge)连接容器,并提供网络隔离和互通功能。bridge 网络模式非常适合单机环境中的容器网络配置。

特点:

  • 1.1 默认网桥:

    docker0 是 Docker 默认创建的虚拟网络桥接器。所有没有显式指定网络模式的容器都会连接到这个默认网桥网络。

  • 1.2 网络隔离:

    连接到 docker0 网桥网络的容器可以相互通信,同时与其他未连接到 docker0 网络的容器以及宿主机隔离

  • 1.3 自动ip分配:

    Docker 会自动为连接到 docker0 网络的容器分配 IP 地址,这些地址通常在 172.17.0.0/16 子网范围内(具体范围可以根据 Docker 配置变化)。

  • 1.4 NAT和端口映射:

    通过 docker0 网桥,Docker 使用网络地址转换(NAT)使容器能够访问外部网络。外部网络无法直接访问容器,除非通过端口映射显式允许。

二、 Host

该网络模式是一种特殊的网络配置选项,它允许容器使用宿主机的网络堆栈。这意味着在 host 网络模式下,容器不会获得独立的网络命名空间,而是与宿主机共享网络配置。

三、 Overlay

Docker 集群中创建跨主机容器通信的网络模式。它允许不同主机上的容器像在同一网络中一样相互通信,适用于使用 Docker Swarm 或 Kubernetes 等编排工具的多主机部署场景。

四、 Ipvlan

IPvlan 模式是一种高级的 Docker 网络模式,它允许您对容器的 IPv4 和 IPv6 地址进行更精细的控制。 它还可以处理第 2 层和第 3 层 VLAN 标记和路由。

五、 Macvlan

Macvlan网络模式是一种高级网络配置选项,它允许用户为每个容器分配唯一的 MAC 地址,使容器能够直接与宿主机的物理网络进行通信。macvlan 模式提供了高性能和良好的隔离性,适用于需要直接访问物理网络的场景。

一、 重要说明:

kexec 实现的是一种快速重启,它可以避免传统的 BIOS/UEFI 启动过程,但实际上系统内的所有进程确实会终止并重新启动。因此,尽管使用 kexec 可以跳过硬件初始化的过程,系统层面的重启依然会发生

    1. 加载新内核kexec -l 命令会将新内核加载到内存中,同时准备好初始内存盘(initrd)等启动所需的数据。
    1. 停止当前进程并执行新内核:当执行 kexec -e 时,当前正在运行的系统会立即终止所有用户态进程,清理掉旧内核占用的资源,然后切换到新内核,重新启动整个系统。
    • 这个过程跳过了 BIOS/UEFI 等硬件初始化步骤(如自检、硬盘探测等),直接由 CPU 开始执行新加载的内核。
    • 但是,所有进程仍然会终止并重新启动,因为新内核需要一个干净的状态。换句话说,从操作系统的角度来看,所有进程都会被关闭,只不过跳过了硬件层面的重启。

二、 安装新内核

2.1 添加公钥

rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org

2.2 添加源


### Name: ELRepo.org Community Enterprise Linux Repository for el7
### URL: https://elrepo.org/

[elrepo]
name=ELRepo.org Community Enterprise Linux Repository - el7
baseurl=https://mirrors.nju.edu.cn/elrepo/archive/elrepo/el7/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elrepo.org
protect=0

[elrepo-testing]
name=ELRepo.org Community Enterprise Linux Testing Repository - el7
baseurl=http://elrepo.org/linux/testing/el7/$basearch/
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elrepo.org
protect=0

[elrepo-kernel]
name=ELRepo.org Community Enterprise Linux Kernel Repository - el7
baseurl=https://mirrors.nju.edu.cn/elrepo/archive/kernel/el7/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elrepo.org
protect=0

[elrepo-extras]
name=ELRepo.org Community Enterprise Linux Extras Repository - el7
baseurl=https://mirrors.nju.edu.cn/elrepo/archive/extras/el7/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elrepo.org
protect=0

2.3 安装TL版本

yum install -y kernel-lt kernel-lt-devel

2.4 查看已安装内核

awk -F\' '$1=="menuentry " {print $2}' /etc/grub2.cfg

三、 切换内核

3.1 更新 GRUB 配置

grub2-mkconfig -o /boot/grub2/grub.cfg

3.2 确保安装了 kexec

yum install kexec-tools

3.3 找到新安装的内核路径

ls -ahl /boot/vmlinuz-*
图
ls -ahl /boot/initramfs-*
图

3.4 加载新内核

kexec -l /boot/vmlinuz-5.4.278-1.el7.elrepo.x86_64 --initrd=/boot/initramfs-5.4.278-1.el7.elrepo.x86_64.img --reuse-cmdline

3.5 切换内核

kexec -e

3.6 检查系统

图

一、 Docker Server 开启 remote api

注意:
方法一和方法二冲突, 只需要配置一个即可

1.1 方法一、 编辑 docker.service

ExecStart=/usr/bin/dockerd -H fd:// \
-H tcp://0.0.0.0:2375 \
-H unix://var/run/docker.sock \
--containerd=/run/containerd/containerd.sock

1.2 方法二、 编辑 /etc/docker/daemon.json

{
"hosts": ["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"]
}

1.3 验证 remote api 是否开启

docker -H tcp://0.0.0.0:2375 version

二、 开启TLS

注意:
docker server 主机上执行

2.1 生成 CA 私钥

openssl genrsa -aes256 -out ca-key.pem 4096

2.2 生成 CA 证书

openssl req -new -x509 -days 365 -sha256 \
-key ca-key.pem \
-out ca.pem \
-subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=dockerapi/OU=dockerspi/CN=$HOST"

2.3 生成 Server 私钥

openssl genrsa -out server-key.pem 4096

2.4 生成 Server 证书请求

openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr

echo subjectAltName = DNS:$HOST,IP:192.168.1.201,IP:127.0.0.1 >> extfile.cnf
echo extendedKeyUsage = serverAuth >> extfile.cnf

2.5 使用 CA证书 签署证书

openssl x509 -req -days 365 -sha256 -in server.csr \
-CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out server-cert.pem \
-extfile extfile.cnf

2.6 修改 service 文件

ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2376 \
--tlsverify \
--tlscacert=/etc/docker/ssl/ca.pem \ # ca 证书
--tlscert=/etc/docker/ssl/server-cert.pem\ # server 证书
--tlskey=/etc/docker/ssl/server-key.pem # server 私钥

systemctl daemon-reload
systemctl restart docker

三、 客户端配置

注意:
docker client 主机上执行

3.1 生成 client 私钥

openssl genrsa -out client-key.pem 4096

3.2 生成 client 证书请求

openssl req -subj '/CN=client' -new -key client-key.pem -out client.csr

3.3 使用 CA 签署证书

echo extendedKeyUsage = clientAuth > extfile-client.cnf

openssl x509 -req -days 365 -sha256 \
-in client.csr \
-CA ca.pem \
-CAkey ca-key.pem \
-CAcreateserial -out client-cert.pem \
-extfile extfile-client.cnf

3.4 访问验证

docker --tlsverify  \
--tlscacert=ca.pem \
--tlscert=client-cert.pem \
--tlskey=client-key.pem \
-H=192.168.1.201:2376 version

3.5 配置全局docker变量

mkdir -pv ~/.docker
cp ./ca.pem ~/.docker/ca.pem
cp ./client-cert.pem ~/.docker/cert.pem
cp ./client-key.pem ~/.docker/key.pem
export DOCKER_HOST=tcp://$HOST:2376 DOCKER_TLS_VERIFY=1

配置完成之后可以直接使用 docker ps 查看

四、 相关问题

4.1 cannot validate certificate for xx.xx.xx.xx because it doesn’t contain any IP SANs

解决: 证书生成的过程中要指定ip, 参照docker

零、 名词解释

本机: Windows 11 (192.168.1.25)
服务器: CentOS 7 (192.168.1.201)

SSH客户端: 192.168.1.25 OpenSSH_for_Windows_8.6p1, LibreSSL 3.4.3
SSH服务端: 192.168.1.201 OpenSSH_7.4p1, OpenSSL 1.0.2k-fips

一、 远程转发&本地转发

两个SSH客户端之间建立一个安全的通道
本地计算机上的端口转发到远程计算机上,或者反向转发,将远程计算机上的端口转发到本地计算机上

1.1 本地转发实例:

应用场景:

  • 绕过防火墙限制, 访问服务器任意资源.

Windows上执行:
ssh -L 8080:localhost:4000 user@remote_server

windows上的8080–>远程服务器的4000

1.2 远程转发实例:

192.168.1.201上执行:

ssh -R 8888:localhost:8006 [email protected]

访问192.168.1.201:8888 –> 192.168.1.200:8006

二、 动态转发(Dynamic Port Forwarding)

ssh -D $port -N user@host

SSH服务端和客户端建立加密连接
SSH客户端还会建立一个socks5代理, 所有从socks出去的流量,都通过这个加密连接转发。

应用场景:

  • 匿名访问互联网
  • 绕过防火墙限制

实例:
Windows上通过 ssh -D 5000 -N [email protected]与服务端建立ssh加密隧道
通过本地socks5的5000端口,实现Windows访问服务器192.168.1.201的任意资源.
图
图

环境

  • 硬件平台: PVE-KVM x86_64
  • 系统版本: CentOS 7.9 64bit
  • 当前软件版本: OpenSSH-7.4p1 OpenSSL-1.02K
  • 目标软件版本: OpenSSH-9.7p1 OpenSSL-1.1.1W

说明

  • OpenSSH-9.7p1依赖OpenSSL-1.1.1及以上版本, 请先升级OpenSSL, 参照这里
  • OpenSSH-8.6后默认为不允许root登录
  • 较新版本的CentOS7中 pam_stack.so模块已经被弃用删除, 请备份 /etc/pam.d/sshd
  • 默认允许使用PAM登录认证;
  • 默认允许使用X11Forwarding图形模块;
  • 需修改ssh_host_rsa_keyssh_host_ecdsa_keyssh_host_ed25519_key这三个文件的权限, OpenSSH-8.6之后缩小了这三个文件的权限为0600, 大于该权限将会导致SSHD启动失败

一、 OpenSSH rpm包构建

1.1 安装依赖

~]# yum install libXt libXt-devel imake gtk2-devel
~]# yum install rpm-build rpmlint rpmdevtools curl

1.2 rpmbuild 目录相关

注意:
下面两个操作请不要使用 root 用户操作

创建目录

~]$ mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}

目录配置

~]$ echo "%_topdir %{getenv:HOME}/rpmbuild" > ~/.rpmmacros

  • %_topdir:RPM 构建的顶层目录宏
  • %{getenv:HOME}:获取用户主目录的环境变量
  • ~/.rpmmacros:用户 RPM 配置文件

1.3 下载源码

  • 下载 OpenSSH-9.7p1和x11-ssh-askpass-1.2.4.1源码到 ~/rpmbuild/SOURCES目录

    ~]$ curl -o ~/rpmbuild/SOURCES/openssh-9.7p1.tar.gz https://mirrors.aliyun.com/pub/OpenBSD/  OpenSSH/portable/openssh-9.7p1.tar.gz
    ~]$ curl -o ~/rpmbuild/SOURCES/x11-ssh-askpass-1.2.4.1.tar.gz https://src.fedoraproject.org/repo /pkgs/openssh/x11-ssh-askpass-1.2.4.1.tar.gz/8f2e41f3f7eaa8543a2440454637f3c3/ x11-ssh-askpass-1.2.4.1.tar.gz

1.4 配置 .SPEC文件

  • 从源码提取.SPEC 文件到SPEC目录

    ~]$ tar -xf ~/rpmbuild/SOURCES/openssh-9.7p1.tar.gz -C ~/rpmbuild/SPECS openssh-9.7p1/contrib/redhat/openssh.spec --strip-components=3 
  • 修改 .SPEC 文件 %pre server 区域新增如下配置, 备份ssh配置

    cp -Rf /etc/ssh{,.back}
  • 修改 .SPEC 文件 %post server 区域下面新增如下配置, 配置sshd

    sed -i -e "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config
    sed -i -e "s/#UsePAM no/UsePAM yes/g" /etc/ssh/sshd_config
    sed -i -e "s/#X11Forwarding no/X11Forwarding yes/g" /etc/ssh/sshd_config
    chmod +x /etc/init.d/sshd
    chmod 600 /etc/ssh/ssh_host_rsa_key
    chmod 600 /etc/ssh/ssh_host_ecdsa_key
    chmod 600 /etc/ssh/ssh_host_ed25519_key
  • 修改 .SPEC 文件 %install 保留原pam配置

    # 注释这行
    #install -m644 contrib/redhat/sshd.pam $RPM_BUILD_ROOT/etc/pam.d/sshd

    # 增加此行
    install -m644 /etc/pam.d/sshd $RPM_BUILD_ROOT/etc/pam.d/sshd
  • 修改%configure 选项, without_openssl选项关闭, 并添加openssl-1.1.1w的路径

    .... # 前面代码省略
    --with-ssl-dir=/usr/openssl \ # 根据 rpm 安装 openssl 的路径决定的
    # %if ! %{without_openssl}
    # --without-openssl \
    # %endif
    .... # 后面代码省略

1.5 检查 .SPEC 文件

如果没有 error就可以下一步构建了

[dev@pve-centos7 SPECS]$ rpmlint ./openssh.spec 
./openssh.spec:95: W: unversioned-explicit-obsoletes ssh
./openssh.spec:132: W: unversioned-explicit-obsoletes ssh-clients
./openssh.spec:137: W: unversioned-explicit-obsoletes ssh-server
./openssh.spec:147: W: unversioned-explicit-obsoletes ssh-extras
./openssh.spec:153: W: unversioned-explicit-obsoletes ssh-extras
./openssh.spec:280: W: macro-in-comment %{_bindir}
./openssh.spec:349: W: mixed-use-of-spaces-and-tabs (spaces: line 349, tab: line 208)
./openssh.spec: W: invalid-url Source1: http://www.jmknoble.net/software/x11-ssh-askpass/ x11-ssh-askpass-1.2.4.1.tar.gz <urlopen error unknown url type: socks5>
./openssh.spec: W: invalid-url Source0: https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/ openssh-9.7p1.tar.gz ''
0 packages and 1 specfiles checked; 0 errors, 9 warnings.
[dev@pve-centos7 SPECS]$

1.6 构建 OpenSSH rpm包

~] $ rpmbuild -ba ~/rpmbuild/SPECS/openssh.spec

如下结果一般就没什么问题了

图

二、 更新 OpenSSH-9.7p1

2.1 输出rpm包详情

[dev@pve-centos7 rpmbuild]$ tree -L 3 RPMS/
RPMS/
└── x86_64
├── openssh-9.7p1-1.el7.x86_64.rpm
├── openssh-askpass-9.7p1-1.el7.x86_64.rpm
├── openssh-askpass-gnome-9.7p1-1.el7.x86_64.rpm
├── openssh-clients-9.7p1-1.el7.x86_64.rpm
├── openssh-debuginfo-9.7p1-1.el7.x86_64.rpm
├── openssh-server-9.7p1-1.el7.x86_64.rpm
├── openssl-1.1.1w-1.el7.x86_64.rpm
├── openssl-debuginfo-1.1.1w-1.el7.x86_64.rpm
└── openssl-devel-1.1.1w-1.el7.x86_64.rpm
1 directory, 9 files
[dev@pve-centos7 rpmbuild]$

2.2 rpm -Uvh 更新 OpenSSH

注意:
更新的前提是, openssl 已经升级至 openssl-1.1.1w 版本

  • 升级openssh的时候, 涉及openssl相关的组件:
    • 只需要升级 openssl-1.1.1w
    • openssl-devel可以不升级
    • openssl-libs 切记不能升级
# 注意 openssl 的版本
[root@pve-centos7 x86_64]# rpm -aq | grep openssl
openssl-libs-1.0.2k-26.el7_9.x86_64
openssl-1.1.1w-1.el7.x86_64
openssl-devel-1.0.2k-1.el7.x86_64
[root@pve-centos7 x86_64]#

# 更新 openssh
[root@pve-centos7 x86_64]# rpm -Uvh openssh-9.7p1-1.el7.x86_64.rpm openssh-server-9.7p1-1.el7.x86_64.rpm openssh-clients-9.7p1-1.el7.x86_64.rpm
Preparing... ################################# [100%]
Updating / installing...
1:openssh-9.7p1-1.el7 ################################# [ 17%]
2:openssh-server-9.7p1-1.el7 ################################# [ 33%]
3:openssh-clients-9.7p1-1.el7 ################################# [ 50%]
Cleaning up / removing...
4:openssh-clients-7.4p1-23.el7_9 ################################# [ 67%]
5:openssh-server-7.4p1-23.el7_9 ################################# [ 83%]
6:openssh-7.4p1-23.el7_9 ################################# [100%]
[root@pve-centos7 x86_64]#

2.3 重启 OpenSSH

注意:
操作不当会导致sshd服务无法启动, 请确保你有其他登录服务器的方式

systemctl daemon-reload
systemctl restart sshd

三、 常见问题

3.1 ssh升级成功但是登录失败

  • 报错: PAM unable to dlopen(/usr/lib64/security/pam_stack.so): /usr/lib64/security/pam_stack.so: cannot open shared object file

  • 原因: pam_stack.so 在较新版本的CentOS中已经弃用并删除

  • 解决: 不升级 /etc/pam.d/sshd 文件, 或者使用旧版本的文件替换

3.2 yum update 报错

  • openssl更新到了 openssl-1.1.1w, 但是对应的openssl-devel和openssl-libs没有更新, 版本的原因, 也不推荐更新这两个
  • 解决: /etc/yum.conf 添加 exclude=openssl

四、 附件

0%