osnosn

  博客园 :: 首页 :: 博问 :: 闪存 :: :: 联系 :: 订阅 订阅 :: 管理 ::

CentOS8_debian11_远程ssh连接在线安装KVM_虚拟化嵌套_安装客户机openwrt_NAT端口映射

转载注明来源: 本文链接 来自osnosn的博客,写于 2022-06-27.

参考

Centos8 最简安装 KVM

  • 使用 Centos8,(2022-8月测试)。
  • 环境是: 不使用本地 console。使用 ssh 远程连接服务器,在线安装 kvm。
    先 ssh 登录服务器,然后运行 tmux 防止意外掉线。
  • lscpu | egrep 'vmx|svm' 检查cpu支持虚拟化。
    vmx 是 Intel的,svm 是 AMD的。
  • lsmod | grep kvm 内核是否加载 kvm 模块。
    如无,则 modprobe kvm 加载。
  • yum install virt-install vm客户机的命令行安装工具
    download size: 12MB, 装完占55MB (32 packages)
  • virt-host-validate 环境检查。输出一堆 PASS。
  • 这个时候,ip addr 显示2个设备: lo, ens33。没有 bridge。
  • yum module install virt 安装 KVM 服务端环境
    download size: 91MB, 装完占330MB (154 packages)
    • 如要,更简的安装,就只装 yum install libvirt,就有 libvirt-daemon 包了。
      download size: 26MB (70 packages) 我没有使用这种极简的方式安装。
  • systemctl start libvirtd 启动daemon
  • systemctl enable libvirtd 激活开机启动
  • 这个时候,ip addr 显示4个: lo, ens33, virbr0, virbr0-nic 。
    virbr0 就是NAT网络。vm客户机可以访问外网,有dnsmasq。
  • virsh net-list 只看到一个名称 default。
  • virsh net-info default 显示这个 default 使用的是 virbr0。
  • 如果要修改 default网络(virbr0) 的 IP 和 网段。
    • virsh net-edit default, 其实就是修改 /etc/libvirt/qemu/networks/default.xml
    • 重启这个default网络。virsh net-destroy default; virsh net-start default 生效。
  • 创建网络,见下文。
  • nmcli device 见到 virbr0是bridge, vribr0-nic 是tun设备。
    DEVICE      TYPE      STATE                   CONNECTION
    ens33       ethernet  connected               ens33
    virbr0      bridge    connected (externally)  virbr0
    lo          loopback  unmanaged               --
    virbr0-nic  tun       unmanaged               --
    
  • nmtui 中看到一个物理网卡,一个 bridge。不要在 nmtui 中修改 virbr0 的配置。
  • 到此,kvm安装完成。创建vm客户机,不能使用"桥接模式"。
    因为没有为本机的物理网口创建网桥。后面用到"桥接"再说。
    网桥设置参考: 【CentOS 8.1 KVM网桥的配置
  • 其他的包:
    • yum install virt-manager 管理vm客户机的 GUI工具。
    • yum install virt-viewer 用于连接vm客户机的桌面, GUI 工具
      (download size: 44MB, 113 packages)
    • dnf install cockpit cockpit-machines Cockpit Web控制台

Debian11 最简安装 KVM

  • 使用 debian11(bullseye),(2022-8月测试)。
  • 环境是: 不使用本地 console。使用 ssh 远程连接服务器,在线安装 kvm。
    先 ssh 登录服务器,然后运行 tmux 防止意外掉线。
  • lscpu | egrep 'vmx|svm' 检查cpu支持虚拟化。
    vmx 是 Intel的,svm 是 AMD的。
  • lsmod | grep kvm 内核是否加载 kvm 模块。
    如无,则 modprobe kvm 加载。
  • apt update
  • apt install libvirt-daemon-system 安装libvirtd服务
    会自动装上 libvirt-daemon, libvirt-client, qemu-kvm, qemu-utils,
    download 207MB, 694MB disk space will be used. 304 packages.
    • qemu-system 是其他架构cpu(arm,ppc,...)的支持。我没装。
  • apt install virtinst 安装virt-install工具
    download 4MB, 20MB disk space will be used. 26 packages.
  • 这时候,ip addr 没有新增 bridge。
    libvirtd 服务已经启动。
    virsh net-list 是空的。
    virsh net-list --all 显示default 是inactive。
  • virsh net-start default 启动default网络
    virsh net-autostart default 自动启动default网络
  • 这时候,ip addr 多出一个 virbr0 的 bridge。
  • virsh net-info default 显示这个 default 网络的信息。
  • virsh net-edit default, 修改 default网络(virbr0) 的 IP 和 网段。
    virsh net-destroy default; virsh net-start default 重启这个default网络,生效。
  • 创建网络,见下文。
  • 到此,kvm安装完成。创建vm客户机,不能使用"桥接模式"。
    因为没有为本机的物理网口创建网桥。后面用到"桥接"再说。
    网桥设置参考: 【如何在 Debian 11 Bullseye Linux 上安装和配置 KVM

创建网络

  • virsh net-create name.xml 创建一个临时网络并启用,重启系统后丢失。
    • 能 start,destroy。但不能设置 autostart。
  • virsh define name.xml 创建一个永久网络。
    • 能 start,destroy。也能设置 autostart。
  • nat网络,带dhcp的例子
    <!--
     文件名: my-wan.xml
    -->
    <network>
      <name>my-wan</name>
      <forward mode='nat'/>
      <bridge name='virbr1' stp='on' delay='0'/>
      <ip address='192.168.22.22' netmask='255.255.255.0'>
        <dhcp>
          <range start='192.168.22.100' end='192.168.22.200'/>
        </dhcp>
      </ip>
    </network>
    
  • 隔离网络,无dhcp的例子
    <!--
     文件名: my-lan.xml
    -->
    <network>
      <name>my-lan</name>
      <bridge name='virbr1' stp='on' delay='0'/>
      <ip address='192.168.22.22' netmask='255.255.255.0'>
      </ip>
    </network>
    

KVM 虚拟化嵌套

  • vm客户机的cpu是否支持vmx。
  • Centos8默认未打开。
    • cat /sys/module/kvm_intel/parameters/nested 0:关闭,1:打开。
    • 修改 /etc/modprobe.d/kvm.confoptions kvm_intel nested=1
      rmmod kvm-intel 或者 modprobe -r kvm-intel 卸载。
      modprobe kvm-intel nested=1 重新加载。
      或者,重启整个系统。
  • Debian11默认是打开的。

安装 VM 客户机

qcow2 的镜像 测试

  • 镜像来源
    https://openwrt.cc/snapshots/targets/x86/64/immortalwrt-x86-64-generic-ext4-combined-efi.qcow2.gz
  • 用 gunzip 解压。
  • mv immortalwrt-.....efi.qcow2 /var/lib/libvirt/images/
  • qemu-img info immortalwrt-.....efi.qcow2 看到这个镜像的虚拟大小是814MB.

Centos8 , Debian11

  • 创建 VM 客户机
    virt-install \
      --virt-type kvm \
      --name opwrt2 \
      --memory 512 \
      --vcpus 1 \
      --cpu host-passthrough \
      --os-variant archlinux \
      --network bridge=virbr0,model=virtio \
      --graphics vnc \
      --import \
      --noautoconsole \
      --autostart \
      --disk path=/var/lib/libvirt/images/immortalwrt-x86-64-generic-ext4-combined-efi.qcow2,bus=virtio,format=qcow2
    
  • virsh 部分命令列表:
    virsh start opwrt2 启动
    virsh list --all 列出所有vm客户机
    virsh suspend opwrt2 暂停
    virsh resume opwrt2 恢复
    virsh dhutdown opwrt2 正常关机
    virsh destroy opwrt2 强制关机
    virsh undefine opwrt2 删除vm客户机
    virsh autostart --disable opwrt2 禁止vm客户机.自动启动
  • 修改 opwrt2 的 LAN口IP。
    virsh console opwrt2 连接终端。按 ^] 退出终端。
    /etc/config/network 中,IP 为 192.168.122.10。
    /etc/init.d/network reload 重启生效。
    或用 uci命令修改IP,见【制作免配置固件】,【官方文档:The UCI system】。
    uci set network.lan.ipaddr='192.168.122.10'
    uci commit network
    /etc/init.d/network reload
    
  • 用 putty 通过 ssh 登录宿主机。
    在 putty 的 主菜单 -> Change Settings... -> Connection -> SSH -> Tunnels 中。
    Source port: 9988, Destination: 192.168.122.10:80, 点击 Add, 点击 Apply
    • 打开浏览器,访问 localhost:9988。配置 opwrt2。
      设置 LAN 的 网关,dns。关掉 LAN 的 dhcp。
    • 配置完成后。直接在 putty 中退出登录宿主机(要等2min才会完全退出),即可。

img 的镜像 测试

  • 镜像来源
    https://downloads.openwrt.org/releases/21.02.3/targets/x86/64/openwrt-21.02.3-x86-64-generic-ext4-combined-efi.img.gz
  • 用 gunzip 解压。
  • mv openwrt-21.02.3-.....efi.img /var/lib/libvirt/images/
  • qemu-img info openwrt-21.02.3-.....efi.img 看到这个镜像的虚拟大小是121MB.
  • 如需扩容,参考:【openwrt_21.02_img_空间扩容_改分区表大小

Centos8 , Debian11

  • 创建 VM 客户机
    virt-install \
      --virt-type kvm \
      --name opwrt21 \
      --memory 256 \
      --vcpus 1 \
      --cpu host-passthrough \
      --os-variant archlinux \
      --network bridge=virbr0,model=virtio \
      --graphics vnc \
      --import \
      --noautoconsole \
      --autostart \
      --disk path=/var/lib/libvirt/images/openwrt-21.02.3-x86-64-generic-ext4-combined-efi.img,bus=virtio,format=raw
    
  • 修改 LAN口IP。配置 openwrt。同 qcow2 的镜像测试。

虚拟机接受kvm关机指令

接受,虚拟机服务的virsh shutdown xxxx指令。
否则实体机的主系统,关闭/重启,要等很久。通常是300秒每个虚机。
/etc/init.d/libvirt-guests/usr/lib/systemd/system/libvirt-guests.service服务脚本的超时设置。
创建的虚机需要一个信道设备org.qemu.guest_agent.0,见【虚拟机op接受kvm关机指令】。

  • 对于openwrt,安装opkg install qemu-ga, op21有4个依赖包,约占用3.4-4MB 空间。重启opwnrt 生效。
    qemu-ga 的配置文件/etc/qemu/qemu-ga.conf,op中没这个文件,需要时,自己创建。
  • 对于 debian,默认就安装了 qemu-guest-agent。
    如果没有,自行安装apt install qemu-guest-agent,重启生效。
  • 其他系统,类似。

NAT 端口映射

  • 参考: 【kvm虚拟机端口映射(端口转发)到宿主机
    • 以下是针对,带有nat的网络"virbr0",进行端口转发。
      防火墙中,已经有"内->外"的 MASQUERADE 的伪装规则,"内->外"的forward转发规则。
    • 检查"包转发"已经打开。sysctl net.ipv4.ip_forward 应该显示=1。
    • 允许"外->内"的转发。
      iptables -I FORWARD -m state -o virbr0 -d 192.168.122.0/24 --state NEW -j ACCEPT
      这个命令只需设置一次。注意 virbr0 和 ip 段,要改成你自己的。
      这个规则也可以限制严格一点,比如,加上 --dport,限制tcp -p tcp
    • 假设 宿主机/实体机 的网口为 eth0, 外部1234端口映射到内网192.168.122.10:5678端口。

      iptables -t nat -I PREROUTING ! -s 192.168.122.0/24 -p tcp --dport 1234 -j DNAT --to-destination 192.168.122.10:5678
      或者
      iptables -t nat -I PREROUTING -i eth0 -p tcp --dport 1234 -j DNAT --to-destination 192.168.122.10:5678
      实现。
      不同端口,使用不同的规则。
      vm客户机的缺省网关需要指向"virbr0"的网关IP,比如"192.168.122.1"。
      从外部连接这个端口,vm客户机中的应用,获取的是真实的"来源IP"。
      debian-10 和 debian-11 中测试成功
    • Centos8 可以用上述的两条 iptables 规则。实测成功
      可以使用firewall-cmd --direct --add-rule ...firewall-cmd --direct --passthrough ... 把这两条iptables规则添加进去。
    • Centos8 用 firewall-cmd 命令实现。测试失败
      firewall-cmd --add-forward-port=port=1234:proto=tcp:toport=5678:toaddr=192.168.122.10
      # 下面这行, "外->内"的forward规则。添加的规则内容正确,但位置不对。所以不能解决问题。
      firewall-cmd --zone libvirt --add-forward
      #没有使用 firewall-cmd --permanent 和 firewall-cmd --reload 虽然不影响 virbr0 的nat网络规则。但影响手工添加的规则。
      
      或者用 firewall-cmd --zone=my_zone --add-rich-rule="..."(未测试)。
    • nft 的办法类似,需要自己写规则。
      参考:【configuring_nat_using_nftables
      ## 这是规则的原理。未实际测试!
      # 假设 宿主机/实体机 的网口为 eth0。宿主机网口的IP为 123.123.123.123,234.234.234.234。
      table ip port_fwd {
        chain forward {
          type filter hook forward priority filter +10; policy accept;
          oifname "virbr0" ip daddr 192.168.122.0/24 ct state new counter accept  #开放"外->内"的转发
          #这条规则需要插入到原有的chain中。即"type filter hook forward"的chain中,如果有的话。
          #因为accept虽然会终止当前chain的rule的匹配,但还会继续匹配其他的(相同的hook)chain中的rule。
          #而drop就完全终止剩余rule的匹配,无论是当前chain的rule还是其他chain的rule。
        }
        chain dstnat {
          type nat hook prerouting priority dstnat +10; policy accept;
          iifname "eth0" tcp dport 1234 counter dnat ip to 192.168.122.10:5678     #添加,端口转发,计数
          #或 iifname "eth0" meta nfproto ipv4 tcp dport 1234 counter dnat ip to 192.168.122.10:5678  #添加,端口转发,计数
          #或 ip saddr != 192.168.122.0/24 tcp dport 1234 counter dnat ip to 192.168.122.10:5678     #添加,端口转发,计数
          #或 ip saddr != 192.168.122.0/24 ip daddr '{123.123.123.123,234.234.234.234}' tcp dport 1234 counter dnat ip to 192.168.122.10:5678     #添加,端口转发,计数(规则严格点)
        }
      }
      
      对于centos-8,firewalld启用。成功
      #centos-8,firewalld启用,实测成功!
      nft insert rule ip filter LIBVIRT_FWI index 0 oifname "virbr0" ip daddr 192.168.122.0/24 ct state new counter accept  #允许"外->内"的转发,只需执行一次
      nft add table ip port_fwd
      nft add chain ip port_fwd dstnat '{type nat hook prerouting priority dstnat +5; policy accept;}'
      nft add rule ip port_fwd dstnat meta l4proto tcp ip saddr != 192.168.122.0/24 tcp dport 1234 counter dnat ip to 192.168.122.10:5678   #端口映射,一个端口一条rule 
      #或 nft add rule ip port_fwd dstnat meta l4proto tcp ip saddr != 192.168.122.0/24 ip daddr '{123.123.123.123, 234.234.234.234}' tcp dport 1234 counter dnat ip to 192.168.122.10:5678   #端口映射,一个端口一条rule (规则严格点)
      
      #或者 nft add rule ip firewalld nat_PRE_libvirt_allow meta l4proto tcp ip saddr != 192.168.122.0/24 tcp dport 1234 counter dnat ip to 192.168.122.10:5678  #加入到已有的chain中(ip firewalld nat_PRE_libvirt_allow)或(ip nat PREROUTING)
      
      vm客户机的缺省网关需要指向"virbr0"的网关IP,比如"192.168.122.1"。
      从外部连接这个端口,vm客户机中的应用,获取的是真实的"来源IP"。
  • 为了宿主机重启之后,保留端口映射。把上述两条规则,写入到 /etc/rc.local 中。
    • 如果有/etc/rc.local这个文件,就保留里面的内容。如果没有这个文件,则自己创建。
      echo -e '#!/bin/sh\n\nexit 0' >> /etc/rc.local; chmod +x /etc/rc.local
    • 然后把规则写在 /etc/rc.local 中, exit 0 这行的前面。
  • 不带nat的网络,如果要映射。也可以。实测成功
    • 首先,允许双向转发。
    • 然后用 SNAT + DNAT 的一对规则实现。
      # 假设"virbr1"是不带nat的隔离网络,"virbr1"的网关IP是"192.168.125.1"。在debian-10中测试成功。
      #允许双向转发
      iptables -I FORWARD -m state -o virbr1 -d 192.168.125.10/32 --state NEW,RELATED,ESTABLISHED -j ACCEPT
      iptables -I FORWARD -m state -i virbr1 -s 192.168.125.10/32 --state RELATED,ESTABLISHED -j ACCEPT
      #SNAT+DNAT 规则, 外部1234端口映射到192.168.125.10:5678端口
      iptables -t nat -I PREROUTING ! -s 192.168.125.0/24 -p tcp --dport 1234 -j DNAT --to-destination 192.168.125.10:5678
      iptables -t nat -I POSTROUTING ! -s 192.168.125.0/24 -d 192.168.125.10 -p tcp --dport 5678 -j SNAT --to-source 192.168.125.1
      
      vm客户机的缺省网关指向哪里都 OK,不影响端口映射。
      从外部连接这个端口1234,vm客户机中的应用,无法获取真实的"来源IP",得到的"来源IP"是网关IP"192.168.125.1"。
    • 如果想让vm客户机中的应用,能够获取真实的"来源IP"。则,
      iptables -I FORWARD -m state -o virbr1 -d 192.168.125.10/32 --state NEW,RELATED,ESTABLISHED -j ACCEPT
      iptables -I FORWARD -i virbr1 -s 192.168.125.10/32 -j ACCEPT
      iptables -t nat -I PREROUTING ! -s 192.168.125.0/24 -p tcp --dport 1234 -j DNAT --to-destination 192.168.125.10:5678
      
      iptables -t nat -I POSTROUTING -s 192.168.125.10 ! -d 192.168.125.0/24 -p tcp --sport 5678 -j MASQUERADE
      #或 iptables -t nat -I POSTROUTING -s 192.168.125.10 ! -d 192.168.125.0/24 -p tcp --sport 5678 -j SNAT --to-source 123.123.123.123  #宿主机外网口IP
      
      记得检查vm客户机的缺省网关指向的是"virbr1"的网关IP,即"192.168.125.1"。
      这样,vm客户机就能获取真实的"来源IP"。

端口映射-其他

  • 无论是 DNAT 还是 SNAT, 内核都会同时创建返回包的匹配状态。
    比如,当有数据包从 1.2.3.4:12345->192.168.122.10:5678,
    内核会创建 192.168.122.10:5678->1.2.3.4:12345 作为 ESTABLISHED 的匹配。
    只是 dnat 是数据包通过网关时改变了目标地址和端口。snat 是数据包通过网关时改变了源地址和端口。
  • 如果 dnat 到本机的 127.0.0.1:5678,
    需要对应网卡的sysctl -w net.ipv4.conf.eth0.route_localnet=1设置,
    echo 1 > /proc/sys/net/ipv4/conf/eth0/route_localnet
    或者设置net.ipv4.conf.all.route_localnet = 1
  • 如果流量大,出现 ip_conntrack: table full, dropping packet 的问题。
    加大表容量, find /proc/sys/net -name nf_conntrack_max。应该找到两个,修改它们的值。
    降低timeout, find /proc/sys/net -name 'nf_conntrack_tcp_timeout*'。修改它们的值。
    针对某个大流量的服务, NOTRACK(不跟踪), 比如80口, 参考【iptables raw表】,
    iptables -t raw -A PREROUTING -d 1.2.3.4 -p tcp --dport 80 -j NOTRACK
    iptables -t raw -A OUTPUT -s 1.2.3.4 -p tcp --sport 80 -j NOTRACK
    iptables -A INPUT -m state --state UNTRACKED -j ACCEPT
    
  • nat/iptables 的其他例子
    debian11_nftables/ip6tables_限制ipv6公网访问特定端口_centos8/debian仅允许部分IPv4访问端口】。

映像文件转换格式

  • 用 qemu-img 。
    • 有 for windows 的命令行版本。
    • debain 装 apt install qemu-utils
    • centos8 装 yum install qemu-img
  • qemu-img -h 查看帮助。resize 是改映像大小,convert 是改格式。
    qemu-img info 映像文件名 查看文件的格式类型。
    支持 img(raw), vhdx, vmdk, vdi, qcow, qcow2, dmg, ... 等很多格式,互相转换。
  • 例子,
    qemu-img resize -f raw 映像文件名.img +200M
    qemu-img convert -f raw -O vhdx 输入的映像名.img 输出的映像名.vhdx

如果有图形桌面

  • 可以安装apt install virt-manager
    可以管理虚拟网络,可以管理虚拟机。
  • 网络管理在这里找。隐藏的挺深,不熟悉的话还找不到。

    可以创建NAT网络,private网络。可以设定网段,指定静态路由。
  • 手动添加qemu-ga的通道

----end----


转载注明来源: 本文链接 https://www.cnblogs.com/osnosn/p/16417701.html
来自 osnosn的博客 https://www.cnblogs.com/osnosn/ .


posted on 2022-08-07 20:38  osnosn  阅读(1214)  评论(0编辑  收藏  举报