WorkingTipsOnFreeRouter

1. 环境

物理机,全隔离环境,可通过隧道开通的proxy(10.xx.xx.xxx:8118)访问互联网.
终极目标:构建一个可自由连接互联网的网段用于虚拟机及虚拟网络方案的验证。

2. 配置步骤

2.1 准备Router虚拟机

virt-manager内创建一个网段为192.168.89.0/24, dhcp关闭,转发模式。而后创建一台ubuntu20.04的虚拟机,配置为1核1G,使用该网络,启动。

启动后配置其网络地址为192.168.89.2/24:

$ cat /etc/netplan/01-netcfg.yaml 
    # This file describes the network interfaces available on your system
    # For more information, see netplan(5).
    network:
      version: 2
      renderer: networkd
      ethernets:
        eth0:
          dhcp4: no
      bridges: 
        br0:
          dhcp4: no
          addresses: [ 192.168.89.2/24 ]
          gateway4: 192.168.100.1
          interfaces:
             - eth0
$ sudo netplan apply
$ sudo hostnamectl set-hostname router
$ sudo vim /etc/hosts
....
127.0.1.1       router  router
....

因为192.168.89.0/24网段内无dncp服务器,dns服务器,因此我们希望Router这台机器用于接管整个网段的地址分配。这个网段我们预留前50个地址用于静态IP使用, 后面的192.168.89.51~192.168.89.254用于dhcp段地址分配。

dnsmasq安装及配置:

$ sudo apt-get install -y dnsmasq
$ sudo systemctl stop systemd-resolved.service
$ sudo systemctl disable systemd-resolved.service
$ sudo systemctl restart dnsmasq
$ sudo  vim /etc/dnsmasq.conf
dhcp-range=192.168.89.51,192.168.89.254,12h
dhcp-option=3,192.168.89.2
interface=br0
bind-interfaces
$ sudo systemctl restart dnsmasq

此时可以新建一台虚拟机接入该网段用于测试,可以看到该网段的dhcp确实由router承载,且分配了网关为192.168.89.2. 但是此时因为router上未开启流量转发,因而此虚拟机使用192.168.89.2作为网关时不能连接外部网络。

使能Ip转发:

$ cat /proc/sys/net/ipv4/ip_forward
0
$ sudo vim /etc/sysctl.conf 
$ sudo sysctl -p
net.ipv4.ip_forward = 1
$ cat /proc/sys/net/ipv4/ip_forward
1

做到这里,我突然想到,如果一个局域网段有两个出口,有可能会带来隐患。不排除有的容器实例里某些诡异的操作会从192.168.89.1直接出也不一定。所以我决定彻底删除这个网段,将这个网段的forward属性也去掉,在libvirtd中,这就是一个完全隔离的网段,而Router这台机器我们将它配置成为一个双网卡的机器,而增加的eth1则连接到另一个网段(192.168.100.4)。

/images/2021_07_01_07_16_52_592x324.jpg

/images/2021_07_01_07_17_26_625x344.jpg

值得注意的是,在更改完isolated网络类型后,虚拟机的配置需要重新确认(libvirtd可能在增删网络配置的过程中将原有的网络回归到default)。

最终router上的网络及路由配置如下:

test@router:~$ cat /etc/netplan/01-netcfg.yaml 
# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: no
      addresses: [ 192.168.89.2/24 ]
      #routes:
      #  - to: 192.168.89.0/24
      #    via: 192.168.89.1
test@router:~$ cat /etc/netplan/02-eth1.yaml 
# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
  version: 2
  renderer: networkd
  ethernets:
    eth1:
      dhcp4: no
      addresses: [ 192.168.100.4/24 ]
      gateway4: 192.168.100.1
test@router:~$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.1   0.0.0.0         UG    0      0        0 eth1
192.168.89.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 eth1

重启过程中发现/etc/resolv.conf无效,执行以下操作:

test@router:/etc$ sudo rm -f resolv.conf 
test@router:/etc$ sudo vim /etc/resolv.conf
nameserver 223.5.5.5
test@router:/etc$ sudo chattr +i /etc/resolv.conf 

执行转发:

# sudo apt-get install -y iptables-persistent
# sudo iptables -t nat -A POSTROUTING -s 192.168.89.1/24 ! -d 192.168.89.0/24 -j SNAT --to-source 192.168.100.4
# apt-get install -y libevent-devel
##### get redsocks
# cd /opt/src/redsocks/
# make clean && make
# cd /opt/src/redsocks
配置
# ./redsocks.sh start

这里值得注意的是,redsocks需要配置为socks5代理才可以让本机访问到外面。

udp转发

外部机器建立ssh隧道用于转发:

# ssh -o GatewayPorts=true -f -N -T -R \*:18888:localhost:18888 docker@10.xx.xx.xxx

外部机器做udp到tcp的socat转发:

# sudo socat tcp-listen:18888,reuseaddr,fork udp:127.0.0.1:53

内部机器做tcp到udp的socat转发:

# socat -T15 udp4-recvfrom:53,bind=10.xx.xxx.xxx,fork tcp:localhost:18888

MakeipvsadmOfflineRPMs

现场测试时,测试人员报告在安装ipvsadm时,有包缺失现象。报错现象如下:

/images/2021_06_26_06_58_40_903x356.jpg

原因是因为在安装ipvsadm时的libnl3依赖更新开始,客户安装的操作系统是centos7.2,而我们做包的系统是>centos7.5以后的,因而导致了libnl3-cli因libnl3的更新抱怨更新后确实依赖而不能进行安装。

解决方案:

/images/2021_06_26_06_57_10_1704x154.jpg

WorkingtipsOnMacVlan

解决问题

LXD 的macvlan组网方式,共享与主机相同的地址段.

环境

环境如下:

lxd1 eth0 192.168.100.61
lxd2 eth0 192.168.100.62
lxd3 eth0 192.168.100.63

创建出的macvlan的profile如下:

# lxc profile show macvlan
config: {}
description: Default LXD profile modified for using macvlan
devices:
  eth0:
    nictype: macvlan
    parent: eth0
    type: nic
name: macvlan

在lxd2主机上创建实例并检查:

# lxc launch 48f7ccdc7b02 test1 --profile default --profile macvlan
# lxc ls
| test1 | RUNNING | 192.168.100.253 (eth0) |      | CONTAINER | 0         |
# lxc exec test1 bash
ping 192.168.100.61/63都可以
无法ping 192.168.100.62

同样在lxd1和lxd3上的容器实例亦无法ping通本机。

workaround

虽然macvlan无法Ping通物理机,因为这是由它的设计原理决定的。但是macvlan可以ping通其他的macvlan, 因而我们可以在主机上分别加上一个额外的macvlan专用来与本机上启动的Lxc容器通信:

以lxd2主机为例,新增一个mynet的macvlan网络设备,指定其地址为192.168.100.72, 而后添加路由,所有到达其产生的LXC容器实例的流量均经过该mynet设备转发:

ip link add mynet link eth0 type macvlan mode bridge
ip addr add 192.168.100.72 dev mynet
ip link set mynet up
ip route add 192.168.100.253 dev mynet

创建完成后,ping本机上的test1容器(192.168.100.253):

PING 192.168.100.253 (192.168.100.253) 56(84) bytes of data.
64 bytes from 192.168.100.253: icmp_seq=1 ttl=64 time=0.088 ms

进入容器后亦可ping通主机.

检查主机上新创建的设备及路由:

# ip addr show mynet
5: mynet@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ether ba:2b:e7:86:33:9a brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.72/32 scope global mynet
       valid_lft forever preferred_lft forever
    inet6 fe80::b82b:e7ff:fe86:339a/64 scope link 
       valid_lft forever preferred_lft forever
# ip route 
default via 192.168.100.1 dev eth0 proto static metric 100 
10.230.202.0/24 dev lxdbr0 proto kernel scope link src 10.230.202.1 
192.168.100.0/24 dev eth0 proto kernel scope link src 192.168.100.62 metric 100 
192.168.100.253 dev mynet scope link 

ToDO

如果要用于生产环境的话,需要考虑:

1. 自动化创建mynet设备并绑定一个额外的同网段IP地址。
2. LXC实例创建后,自动在主机层面创建经由mynet设备的路由。
3. LXC销毁后,自动删除该LXC IP对应的路由。

iPadiPhoneMirroringDisplay

1. 硬件/配置

用来作为AirPlay Mirror Server的设备是一个brix投影电脑,配置为:

Intel(R) Core(TM) i3-4010U CPU @ 1.70GHz
16 GB Ram
120 GB msata ssd
1000 M ethernet

安装操作系统为ArchLinux.

2. 软件/安装配置步骤

通过yay安装uxplay:

yay uxplay

使能服务:

systemctl start avahi-daemon
systemctl enable avahi-daemon

此时最好重启,因uxplay安装过程中有涉及到其他模块。重启后可以通过以下命令开启uxplay, 此时IOS的屏幕镜像中找到uxplay的条目。

$ sudo uxplay &

3. 自动Serving

上述的场景针对个人使用一般情况下是够了,但是如果使用者是家人,则上述的步骤需要改进。

首先我们要让ArchLinux自动登录,自动登录后进入到图形界面。
然后我们要用uxplay随桌面启动而启动。
启动后我们需要禁用电源管理,以使得在长时间无键盘鼠标输入后屏幕依然可以保持常亮。
针对IOS普遍存在的设备上可用空间较少的缘故,我们需要开启brix盒子上的samba服务,让IOS可以使用外置存储用来播放视频。
IOS本身需要安装支持SAMBA的播放软件。

分而击之,一一解决这些问题。

3.1 自动登录

以用户dash为例,说明如何实现lightdm+awesome的自动登录过程:

$ sudo pacman -S lightdm lxde
# pacman -S xorg lightdm-gtk-greeter xterm xorg-xinit awesome
# systemctl enable lxdm.service
# vim /etc/lxdm/lxdm.conf
####autologin=dgod
autologin=dash
# vim /home/dash/.dmrc
[Desktop]
Session=awesome
# groupadd -r autologin
# gpasswd -a dash autologin
# vim /etc/lightdm.conf
[LightDM]
在此条目中做如下修改:
user-session = awesome
autologin-user = dash
autologin-session = awesome
[Seat:*]
在此条目中做如下修改:   
pam-service=lightdm
pam-autologin-service=lightdm-autologin
greeter-session=lightdm-gtk-greeter
user-session=awesome
session-wrapper=/etc/lightdm/Xsession
autologin-user=dash
autologin-user-timeout=0

3.2 uxplay自启动

sudo uxplay & 添加到~/.config/awesome/rc.lua条目中即可,具体步骤参见awesome的一般配置文档。需要注意的是dash用户需要免密码使用sudo .

3.3 禁用屏幕电源管理

sudo xset -dpms & 添加到~/.config/awesome/rc.lua条目中即可.

3.4 samba服务

参考ArchLinux Wiki条目

3.5 IOS samba player

软件市场安装vlc, vlc中内建对samba Server的流媒体播放支持。

WorkingTipsOnGPUPassthrough

Hardware Info

gpu info:

root@usbserver:~# lspci | grep -i nvidia
01:00.0 VGA compatible controller: NVIDIA Corporation GP106M [GeForce GTX 1060 Mobile] (rev a1)
01:00.1 Audio device: NVIDIA Corporation GP106 High Definition Audio Controller (rev a1)
root@usbserver:~# uname -a
Linux usbserver 5.4.0-74-generic #83-Ubuntu SMP Sat May 8 02:35:39 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
root@usbserver:~# cat /etc/issue
Ubuntu 20.04.2 LTS \n \l

Newly installed system, install qemu/libvirtd/virt-manager via:

# apt-get update -y && apt-get install -y virt-manager

Configuration

Remove current NVIDIA or opensource Nouveau driver:

root@usbserver:~# apt-get remove --purge nvidia*

Add driver blacklist:

# vim /etc/modprobe.d/blacklist.conf
....
blacklist amd76x_edac #this might not be required for x86 32 bit users.
blacklist vga16fb
blacklist nouveau
blacklist rivafb
blacklist nvidiafb
blacklist rivatv
blacklist lbm-nouveau
options nouveau modeset=0
alias nouveau off
alias lbm-nouveau off

Disable modset and add intel_iommu for default grub setting and update grub:

# vim /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="maybe-ubiquity nouveau.modeset=0 intel_iommu=on"
# update-grub2

Disable nouveau kernel:

# echo options nouveau modeset=0 | sudo tee -a /etc/modprobe.d/nouveau-kms.conf
# update-initramfs -u

On the above output for lspci -nn | grep -i nvidia, record the GPU id 10de:1c20 and 10de:10f1, create /etc/modprobe.d/vfio.conf, add corresponding GPU PCI Ids:

# vim /etc/modprobe.d/vfio.conf
options vfio-pci ids=10de:10f1,10de:1c20

Edit /etc/default/grub for adding vfio-ids:

# vim /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="maybe-ubiquity nouveau.modeset=0 intel_iommu=on vfio-pci.ids=10de:1c20,10de:10f1"
# update-grub2

Add vfio modules into initrd:

# vim /etc/initramfs-tools/modules

vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
# update-initramfs -u

Now restart host machine, after boot check configurations for vfio:

# dmesg | grep -i iommu
# dmesg | grep -i dmar
# lspci -vv
See if the  drive in use is vfio-pci

VM