WorkingTipsOnOpenWRTCrossGFW

硬件配置

2核2G, 虚拟机, 其磁盘文件为openwrt-21.02.0-rc3-x86-64-generic-ext4-combined.img.

网络配置

隔离网络:

/images/2021_08_17_13_57_12_682x128.jpg

NAT网络:

/images/2021_08_17_13_57_12_682x128.jpg

启动完毕后,安装以下opkg包:

# opkg install redsocks

OpenWRT中配置:

Wan:

./images/2021_08_17_13_59_55_881x449.jpg

/images/2021_08_17_14_03_07_467x160.jpg

LAN:

/images/2021_08_17_14_00_17_604x551.jpg

/images/2021_08_17_14_02_14_508x152.jpg

Enable dhcp server:

/images/2021_08_17_14_02_34_580x398.jpg

Devices:

/images/2021_08_17_14_03_45_953x307.jpg

/images/2021_08_17_14_04_05_478x424.jpg

/images/2021_08_17_14_04_21_610x382.jpg

DNS:

/images/2021_08_17_14_04_47_552x604.jpg

redsocks items

/etc/redsocks.conf:

base {
        // debug: connection progress & client list on SIGUSR1
        log_debug = off;

        // info: start and end of client session
        log_info = on;

        /* possible `log' values are:
         *   stderr
         *   "file:/path/to/file"
         *   syslog:FACILITY  facility is any of "daemon", "local0"..."local7"
         */
        // log = stderr;
        // log = "file:/path/to/file";
        log = "syslog:local7";

        // detach from console
        daemon = on;

        /* Change uid, gid and root directory, these options require root
         * privilegies on startup.
         * Note, your chroot may requre /etc/localtime if you write log to syslog.
         * Log is opened before chroot & uid changing.
         */
        // user = nobody;
        // group = nobody;
        // chroot = "/var/chroot";

        /* possible `redirector' values are:
         *   iptables   - for Linux
         *   ipf        - for FreeBSD
         *   pf         - for OpenBSD
         *   generic    - some generic redirector that MAY work
         */
        redirector = iptables;
}

redsocks {
        /* `local_ip' defaults to 127.0.0.1 for security reasons,
         * use 0.0.0.0 if you want to listen on every interface.
         * `local_*' are used as port to redirect to.
         */
        local_ip = 192.168.89.254;
        local_port = 12345;

        // listen() queue length. Default value is SOMAXCONN and it should be
        // good enough for most of us.
        // listenq = 128; // SOMAXCONN equals 128 on my Linux box.

        // `max_accept_backoff` is a delay to retry `accept()` after accept
        // failure (e.g. due to lack of file descriptors). It's measured in
        // milliseconds and maximal value is 65535. `min_accept_backoff` is
        // used as initial backoff value and as a damper for `accept() after
        // close()` logic.
        // min_accept_backoff = 100;
        // max_accept_backoff = 60000;

        // `ip' and `port' are IP and tcp-port of proxy-server
        // You can also use hostname instead of IP, only one (random)
        // address of multihomed host will be used.
        ip = 10.50.208.147;
        port = 8118;


        // known types: socks4, socks5, http-connect, http-relay
        type = socks5;

        // login = "foobar";
        // password = "baz";
}

redudp {
        // `local_ip' should not be 0.0.0.0 as it's also used for outgoing
        // packets that are sent as replies - and it should be fixed
        // if we want NAT to work properly.
        local_ip = 127.0.0.1;
        local_port = 10053;
        // `ip' and `port' of socks5 proxy server.
        ip = 10.0.0.1;
       port = 1080;
        login = username;
        password = pazzw0rd;

        // redsocks knows about two options while redirecting UDP packets at
        // linux: TPROXY and REDIRECT.  TPROXY requires more complex routing
        // configuration and fresh kernel (>= 2.6.37 according to squid
        // developers[1]) but has hack-free way to get original destination
        // address, REDIRECT is easier to configure, but requires `dest_ip` and
        // `dest_port` to be set, limiting packet redirection to single
        // destination.
        // [1] http://wiki.squid-cache.org/Features/Tproxy4
        dest_ip = 8.8.8.8;
        dest_port = 53;

        udp_timeout = 30;
        udp_timeout_stream = 180;
}

dnstc {
        // fake and really dumb DNS server that returns "truncated answer" to
        // every query via UDP, RFC-compliant resolver should repeat same query
        // via TCP in this case.
        local_ip = 127.0.0.1;
        local_port = 5300;
}

// you can add more `redsocks' and `redudp' sections if you need.

/etc/init.d/redsocks content:

##### /etc/init.d/redsocks######
#!/bin/sh /etc/rc.common
# Copyright (C) 2007 OpenWrt.org

START=90

# check if configuration exists
[ -e "/etc/redsocks.conf" ] || exit 0

start() {
        if [ -e "/var/run/redsocks.pid" ]; then
                echo "redsocks is already running"
                exit 0
        fi

        /bin/echo -n "running redsocks ..."

        # startup the safety-wrapper for the daemon
        /usr/sbin/redsocks -p /var/run/redsocks.pid

        /bin/echo " done"
}

stop() {
        if [ ! -e "/var/run/redsocks.pid" ]; then
                echo "redsocks is not running"
                exit 0
        fi

        /bin/echo -n "stopping redsocks ..."

        # kill the process
        /bin/kill $(cat /var/run/redsocks.pid)
        rm /var/run/redsocks.pid

        echo " done"
}

Iptables rules:

iptables -t nat -N REDSOCKS
# Ignore LANs IP address
iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN
# Anything else should be redirected to redsocks's local port
iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-ports 12345
iptables -t nat -I zone_lan_prerouting -j REDSOCKS

Then with a reverse proxy you could cross gfw.
Reverse connect:

Internet machine(with 53 as its dns server):

ssh -o GatewayPorts=true -f -N -T -R *:18888:localhost:18888 docker@10.xxxxx
ssh -o GatewayPorts=true -f -N -T -R *:8118:10.10.3.19:1080 docker@10.xxxxxx
sudo socat tcp-listen:18888,reuseaddr,fork udp:127.0.0.1:53

Intranet machine:

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

WorkingTipsOnArchAnbox

VM Prepration

Download qcow2 from gitlab(arch built), then start a vm.
Update the mirrorlist from https://archlinux.org/mirrorlist/

Steps

Install yay:

$ sudo pacman -Sy git fakeroot vim pacman-mirrorlist
$ sudo pacman -Sy base-devel
$ cd /opt
$ sudo git clone https://aur.archlinux.org/yay-git.git
$ sudo chown -R  arch:arch ./yay-git/
$ cd yay-git
$ makepkg -si

Install linux-mainline:

$ yay linux-mainline

WorkingTipsOnRPI4Android

flash

Create a new partition:

/images/2021_08_11_17_21_41_712x293.jpg

Create new unkown partitions, then a userdata partition:

/images/2021_08_11_17_23_47_712x289.jpg

Layout:

/images/2021_08_11_17_24_20_951x286.jpg

p1: 128MB for boot (fat32, boot & lba)
p2: 768MB for /system
p3: 128MB for /vendor
p4: remainings for /data (ext4)

Manage flags:

/images/2021_08_11_17_25_39_369x454.jpg

Final layout:

/images/2021_08_11_17_26_24_921x217.jpg

Write steps

Write via following steps:

➜  ~ cd rpi4 
➜  rpi4 ls
bcm2711-rpi-4-b.dtb  boot  ramdisk.img  system.img  vc4-kms-v3d-pi4.dtbo  vendor.img  zImage
➜  rpi4 sudo dd if=system.img of=/dev/sdb2 bs=1M
768+0 records in
768+0 records out
805306368 bytes (805 MB, 768 MiB) copied, 12.812 s, 62.9 MB/s
➜  rpi4 sudo dd if=vendor.img of=/dev/sdb3 bs=1M
128+0 records in
128+0 records out
134217728 bytes (134 MB, 128 MiB) copied, 2.25087 s, 59.6 MB/s
➜  rpi4 sudo mount /dev/sdb1 /mnt
➜  rpi4 sudo cp boot/* /mnt
➜  rpi4 sudo cp zImage bcm2711-rpi-4-b.dtb ramdisk.img /mnt
➜  rpi4 sudo mkdir /mnt/overlays
➜  rpi4 sudo cp vc4-kms-v3d-pi4.dtbo /mnt/overlays 
➜  rpi4 sudo sync

WorkingTipsOnRPI4Android

WorkingSteps

Operation steps:

# adb connect 192.168.1.113
already connected to 192.168.1.113:5555
# adb shell
rpi4:/ 

Or:

# adb root
restarting adbd as root
# adb shell
rpi4:/ # ls
acct boot       charger data          dev  init.environ.rc      init.usb.rc      mnt proc             res    sepolicy system     vendor_service_contexts 
apex bugreports config  debug_ramdisk etc  init.rc              init.zygote32.rc odm product          sbin   storage  ueventd.rc 
bin  cache      d       default.prop  init init.usb.configfs.rc lost+found       oem product_services sdcard sys      vendor     
rpi4:/ # exit

OR:

adb remount
remount succeeded
➜  Downloads adb shell  
rpi4:/ # cd /system/bin/                                                                                                                                                                     
rpi4:/system/bin # touch fff
rpi4:/system/bin # rm fff                                                                                                                                                                    
rpi4:/system/bin #                                                                           


Shutdown the phone:

sudo adb shell reboot -p

sddmAndNestedLogin

目标

系统化说明如何在vdi设备和idv设备上开启sddm的nested模式下Multiseat登录支持。

环境准备

vdi设备信息如下:

Intel(R) Celeron(R) CPU  J1900  @ 1.99GHz
# free -m
              总计         已用        空闲      共享    缓冲/缓存    可用
内存:        3826         487        1676         317        1662        2758
交换:           0           0           0
# df -h
文件系统        容量  已用  可用 已用% 挂载点
udev            1.9G     0  1.9G    0% /dev
tmpfs           383M  872K  382M    1% /run
/dev/sda5        27G  5.1G   21G   20% /
# cat /etc/issue
Ubuntu 18.04.5 LTS \n \l
#  uname -a
Linux xxxx 5.3.0-24-generic #26~18.04.2-Ubuntu SMP Tue Nov 26 12:34:22 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

安装必要的包:

# sudo apt-get update -y
# sudo apt-get upgrade -y
# sudo apt-get install -y sddm xfce4 unzip autoconf automake libtool pkg-config build-essential
# sudo apt-get install -y x11proto-dev xserver-xorg-dev libxcb-util-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-shm0-dev libxcb-randr0-dev vim cmake cmake-extras extra-cmake-modules libpam-dev libxcb-xkb-dev qt5-default libqt5qml5 qt5-qmltooling-plugins qtdeclarative5-dev qttools5-dev xutils-dev

编译相关包

编译xf86-video-nested:

$ git clone https://github.com/smemc/xf86-video-nested.git
$ cd xf86-video-nested
$ ./autogen.sh
$ ./configure --prefix=/usr
$ make -j2
$ sudo make install

编译sddm-nested:

$ git clone https://github.com/purplepalmdash/sddm-nested-multiseat.git
$ cd sddm-nested
$ mkdir build && cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/usr       -DCMAKE_BUILD_TYPE=Release        -Wno-dev ..
$ make -j2
$ sudo make install
$ sudo install -v -dm755 -o sddm -g sddm /var/lib/sddm
$ sddm --example-config > sddm.example.conf
$ sudo cp -v  sddm.example.conf /etc/sddm.conf

生成配置文件:

cat > /etc/pam.d/sddm << "EOF" &&
# Begin /etc/pam.d/sddm

auth     requisite      pam_nologin.so
auth     required       pam_env.so

auth     required       pam_succeed_if.so uid >= 1000 quiet
auth     include        common-auth

account  include        common-account
password include        common-password

session  required       pam_limits.so
session  include        common-session

# End /etc/pam.d/sddm
EOF

cat > /etc/pam.d/sddm-autologin << "EOF" &&
# Begin /etc/pam.d/sddm-autologin

auth     requisite      pam_nologin.so
auth     required       pam_env.so

auth     required       pam_succeed_if.so uid >= 1000 quiet
auth     required       pam_permit.so

account  include        common-account

password required       pam_deny.so

session  required       pam_limits.so
session  include        common-session

# End /etc/pam.d/sddm-autologin
EOF

cat > /etc/pam.d/sddm-greeter << "EOF"
# Begin /etc/pam.d/sddm-greeter

auth     required       pam_env.so
auth     required       pam_permit.so

account  required       pam_permit.so
password required       pam_deny.so
session  required       pam_unix.so
-session optional       pam_systemd.so

# End /etc/pam.d/sddm-greeter
EOF

配置分屏

定义出Intel显卡的输出口:

# vim  /etc/X11/xorg.conf.d/20-intel.conf 
Section "Device"
   Identifier  "Intel Graphics"
   Driver      "intel"
   Option      "AccelMethod"  "sna"
   Option      "TearFree"    "true"
   Option      "DRI"    "3"
   Option      "Monitor-VGA" "VGA"
   Option      "Monitor-HDMI2" "HDMI2"
EndSection

定义出显示器配置:

Section "Monitor"
	Identifier	"VGA"
EndSection

Section "Monitor"
	Identifier	"HDMI2"
	Option		"Position"	"1920 0"
	Option		"PreferredMode"	"1920x1080"
EndSection

Section "Screen"
	Identifier	"VGA"
	Monitor		"VGA"
	SubSection "Display"
		Depth	24
		Modes	"1920x1080"
	EndSubSection
EndSection

Section "Screen"
	Identifier	"HDMI2"
	Monitor		"HDMI2"
	SubSection "Display"
		Depth	24
		Modes	"1920x1080"
	EndSubSection
EndSection

Section "ServerLayout"
	Identifier	"L1"
	Screen		"VGA"	0 0
	Screen		"HDMI2"		1920 0
	Option		"BlankTime"	"0"
	Option		"StandbyTime"	"0"
	Option		"SuspendTime"	"0"
	Option		"OffTime"	"0"
EndSection


Section "ServerFlags"
    Option        "BlankTime"    "0"
    Option        "StandbyTime"    "0"
    Option        "SuspendTime"    "0"
    Option        "OffTime"    "0"
EndSection

Section "Extensions"
    Option        "DPMS"    "Disable"
EndSection

定义出seat1seat2的配置:

# vim /etc/X11/seat1.conf 
Section "Module"
    Load        "shadow"
    Load        "fb"
EndSection

Section "Device"
    Identifier    "seat1"
    Driver        "nested"
EndSection

Section "Screen"
    Identifier    "Screen1"
    Device        "seat1"
    DefaultDepth    24
    SubSection "Display"
        Depth 24
        #Modes "3840x2160"
        Modes "1920x1080"
    EndSubSection
    Option        "Origin"    "1920 0"
EndSection

Section "ServerLayout"
    Identifier    "Nested"
    Screen        "Screen1"
    Option        "AllowEmptyInput"    "true"
    Option        "BlankTime"    "0"
    Option        "StandbyTime"    "0"
    Option        "SuspendTime"    "0"
    Option        "OffTime"    "0"
EndSection

Section "ServerFlags"
        Option "BlankTime" "0"
        Option "StandbyTime" "0"
        Option "SuspendTime" "0"
        Option "OffTime" "0"
EndSection
# vim /etc/X11/seat2.conf 
Section "Module"
    Load        "shadow"
    Load        "fb"
EndSection

Section "Device"
    Identifier    "seat2"
    Driver        "nested"
EndSection

Section "Screen"
    Identifier    "Screen1"
    Device        "seat2"
    DefaultDepth    24
    SubSection "Display"
        Depth 24
        Modes "1920x1080"
    EndSubSection
    Option        "Origin"    "0 0"
EndSection

Section "ServerLayout"
    Identifier    "Nested"
    Screen        "Screen1"
    Option        "AllowEmptyInput"    "true"
    Option        "BlankTime"    "0"
    Option        "StandbyTime"    "0"
    Option        "SuspendTime"    "0"
    Option        "OffTime"    "0"
EndSection

Section "ServerFlags"
        Option "BlankTime" "0"
        Option "StandbyTime" "0"
        Option "SuspendTime" "0"
        Option "OffTime" "0"
EndSection

定义出USB口与seat的映射关系(注意前置的口USB编号与机箱后部的USB编号的对应关系):

# vim /etc/udev/rules.d/70-seat.rules 
SUBSYSTEM=="input", DEVPATH=="/devices/pci0000:00/0000:00:14.0/usb1/1-1/*", TAG+="seat",  ENV{ID_SEAT}="seat2", TAG+="master-of-seat", PROGRAM="/usr/bin/sed -n 's/.*startseat=\([^ ]*\).*/\1/p' /proc/cmdline", RESULT=="true"
SUBSYSTEM=="input", DEVPATH=="/devices/pci0000:00/0000:00:14.0/usb1/1-4/*", TAG+="seat",  ENV{ID_SEAT}="seat2", TAG+="master-of-seat", PROGRAM="/usr/bin/sed -n 's/.*startseat=\([^ ]*\).*/\1/p' /proc/cmdline", RESULT=="true"
SUBSYSTEM=="input", ATTRS{name}=="Power Button", TAG+="seat",  ENV{ID_SEAT}="seat2", TAG+="master-of-seat", PROGRAM="/usr/bin/sed -n 's/.*startseat=\([^ ]*\).*/\1/p' /proc/cmdline", RESULT=="true"
#SUBSYSTEM=="input", DEVPATH=="/devices/pci0000:00/0000:00:14.0/usb1/1-9/*", TAG+="seat",  ENV{ID_SEAT}="seat1", TAG+="master-of-seat", PROGRAM="/usr/bin/sed -n 's/.*startseat=\([^ ]*\).*/\1/p' /proc/cmdline", RESULT=="true"

SUBSYSTEM=="input", DEVPATH=="/devices/pci0000:00/0000:00:14.0/usb1/1-2/*", TAG+="seat",  ENV{ID_SEAT}="seat1", TAG+="master-of-seat", PROGRAM="/usr/bin/sed -n 's/.*startseat=\([^ ]*\).*/\1/p' /proc/cmdline", RESULT=="true"
#SUBSYSTEM=="input", DEVPATH=="/devices/pci0000:00/0000:00:14.0/usb1/1-6/*", TAG+="seat",  ENV{ID_SEAT}="seat1", TAG+="master-of-seat", PROGRAM="/usr/bin/sed -n 's/.*startseat=\([^ ]*\).*/\1/p' /proc/cmdline", RESULT=="true"
SUBSYSTEM=="input", ATTRS{name}=="Sleep Button", TAG+="seat",  ENV{ID_SEAT}="seat1", TAG+="master-of-seat", PROGRAM="/usr/bin/sed -n 's/.*startseat=\([^ ]*\).*/\1/p' /proc/cmdline", RESULT=="true"

开启multi-seat:

# vim /etc/default/grub
.....
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash startseat=true"
GRUB_CMDLINE_LINUX="startseat=true"
....
# update-grub2

重启后验证:

# cat /proc/cmdline 
BOOT_IMAGE=/boot/vmlinuz-5.3.0-24-generic root=UUID=50368a13-e1d7-4699-8b3b-b5ffc1d148e6 ro startseat=true quiet splash startseat=true vt.handoff=1

配置多用户登录

创建两个用户seat1seat2:

# useradd -m seat1
# useradd -m seat2
# passwd seat1
# passwd seat2

配置其自动登录([AutoLogin]内只保留如下所示部分):

# cat /etc/sddm.conf | more
[Autologin]
# Whether sddm should automatically log back into sessions when they exit
# Whether sddm should automatically log back into sessions when they exit
Relogin=false,false
SeatName=seat1,seat2
#Session=awesome,awesome
Session=xfce,xfce
User=seat1,seat2
....

Awesome自启动项

awesome的情景下,我们配置其登录方式为:

# su seat1
$ /bin/bash
$ mkdir -p ~/.config/awesome
$ cp /etc/xdg/awesome/rc.lua ~//.config/awesome
$ vim ~/.config/awesome/autorun.sh

$ vim ~/.config/awesome/autorun.sh 
    #!/usr/bin/env bash
    
    function run {
      if ! pgrep -f $1 ;
      then
        $@&
      fi
    }
    run sleep3 && /opt/ctg/CtyunClouddeskUniversal/CtyunClouddeskUniversal
$ vim ~/.config/awesome/rc.lua 
最后一行添加:
awful.spawn.with_shell("~/.config/awesome/autorun.sh")
$ chmod 777 ~/.config/awesome/autorun.sh 
$ rm -rf /tmp/awesome/
$ cp -r ~/.config/awesome /tmp
$ exit
exit
$ exit
# su seat2
$ /bin/bash
$ cp -r /tmp/awesome/ ~/.config/
$ chmod 777 ~/.config/awesome/autorun.sh 
$ exit
exit
$ exit

现在重启后即可看到结果,其结果表现为,两路显示独立输出且进入到idv登录前界面。