نویسنده: m.javidi

  • secure-boot_arch-linux

    Inatall Arch Linux with secure boot + encrypt (luks2 cryptlvm) partition + unlock lvm encrypt with TPM2 + Dualboot with windows

    Arch Linux Install – Introduction

    This guide will tell you how to install fully encrypted Arch base system with SecureBoot enabled . This specific guide uses Unified Boot Image for booting and therefore there is no need for software like GRUB.

    Check this list before starting!

    Your computer supports SecureBoot/UEFI
    Your computer allows for enrollment of your own secureboot keys
    Your computer does not have manufacturer’s backdoors
    You DO NOT need dualboot with windows You can choose whether you want Microsoft CA when enrolling keys

    If you are not interested in SecureBoot, you can just skip last section of this document.

    Preparing USB and booting the installer

    Download the latest Archlinux ISO and copy it to your USB:

    sudo dd if=/path/to/file.iso of=/dev/sdX status=progress
    sync

    or if you are using windows can download rufus and create a bootable usb (GPT bootable) or BalenaEtcher

    Reboot your machine (if enabled => disable secureboot in BIOS) and boot ArchLinux USB.

    When your installer has booted, especially on laptop, you may want to enable WiFi connection:

    iwctl
    station list
    station wlan0 connect SSID (or station wlan0 connect-hidden SSID)
    <password prompt>
    exit

    then if not get ip, run:

     Run this command for get ip
    dhcpcd
    
     check net
    ping -c3 archlinux.org

    Disk partitioning

    See your disk status:

     to get list of partition and structure of it
    
    lsblk

    Following example assumes you have a nvme drive (/dev/nvme0nX). Your drive may as well report as (/dev/sdX).

    You can use your favoruite tool, that supports creating the GPT partiton, for example cfdisk:

     change nvme0nX with your disk data (get from lsblk)
    cfdisk /dev/nvme0nX

    and then choose gpt partiton table and create something like this:

    +----------------------+----------------------+----------------------+
    | /dev/nvme0n1p1       |   /dev/nvme0n1p2 (encrypted using LUKS2)    |
    | 1024 MB              |                  68 GB                      |
    +----------------------+---------------------------------------------+
    | EFI Boot Partition   |         LVM          |        LVM           |
    |                      |                      |                      |
    | /boot/efi            |          /           |       [Swap]         |
    |                      |                      |                      |
    |                      |     /dev/vg/root     |     /dev/vg/swap     |
    |                      |                      |                      |
    | 1024 MB              |         60 GB        |        8 GB          |
    +----------------------+----------------------+----------------------+

    So we need to EFI partitions (if already installed windows or etc… – or you have efi partiton befor it => dont need to recreate or format it just mount it)
    for root partiton Create ext4 partiton
    and creat a SWAP pariton
    at the end => choose Write from bottom menu to save your change (Carefull !!!)

    Format:

     EFI -> (if already installed windows or etc... - or you have efi partiton befor it => dont need to recreate or format it just mount it)
    mkfs.fat -F32 /dev/nvme0n1p1
    
     Encrypted DISK for (root and swap)
    cryptsetup luksFormat --type luks2 /dev/nvme0n1p2

    Now we can create encrypted volume and open it (–perf options are optional and recommended for SSD):

    cryptsetup open --perf-noreadworkqueue --perf-nowriteworkqueue --persistent /dev/nvme0n1p2 cryptlvm

    Configuring LVM and formatting root partition:

    pvcreate /dev/mapper/cryptlvm
    
    vgcreate vg /dev/mapper/cryptlvm
    
     Create 60 GB space for root
    lvcreate -L 60G vg -n root
    
     Use another space for SWAP (68 - 60 = 8 GB)
    lvcreate -l 100%FREE vg -n swap
    
     format root
    mkfs.ext4 /dev/vg/root
    
     Create swap
    mkswap /dev/vg/swap

    After all is done we need to mount our drives:

     root
    mount /dev/vg/root /mnt
    
     swap
    swapon /dev/vg/swap
    
     boot
    mkdir -p /mnt/boot/efi
    mount /dev/nvme0n1p1 /mnt/boot/efi

    Now for see result

    Run:

    lsblk

    For best performance in download speed from arch repo

    go to mirror list file and set best arch repo at first – example:
    add : Best Repo for IRAN – copy one of them and set it in the first repo in this file

    nano /etc/pacman.d/mirrorlist

    System bootstraping

    In the next step it is recommended to install CPU microcode package. Depending on whether you have intel of amd you should apend intel-ucode or amd-ucode to your pacstrap

    My pacstrap presents as follows:

    pacstrap -K /mnt base linux linux-firmware YOURUCODEPACKAGE sudo nano lvm2 dracut sbsigntools iwd git efibootmgr binutils dhcpcd

    Generate fstab:

    genfstab -U /mnt >> /mnt/etc/fstab

    Optional Step

    For esay-write script in arch (In real installation we not have option for copy paste script so copy all script file to a usb flash drive and mount it after generate fstab)
    Create this files in usb flash drive

    usb2
    |
    ├── cmdline.conf
    ├── flags.conf
    ├── secureboot.conf
    ├── dracut-install.sh
    ├── dracut-remove.sh
    ├── 60-dracut-remove.hook
    ├── 90-dracut-install.hook
    └── zz-sbctl.hook

    !!!(files content is in the bellow)!!!

    Connect the usb flash drive to computer and run:

     Check place of usb => SdaX or SdbX etc ...
    lsblk
    
     mount usb2 to /usb2 folder
    mount /dev/sdbX /mnt/usb2 --mkdir

    Now you can chroot to your system and perform some basic configuration:

    arch-chroot /mnt

    Set the root password:

    passwd

    My Optional suggestion is to also install man for additional help you may require:

     manual for package Ex. -> man ls
    pacman -Syu man-db

    Set timezone and generate /etc/adjtime:

    ln -sf /usr/share/zoneinfo/<Region>/<city> /etc/localtime
    hwclock --systohc

    Set your desired locale:

     at /etc/locale.gen -> uncomment locales you want
     with ctrl+w search for locales ex. enUS and remove ->  sign at first it's line
    nano /etc/locale.gen

    Configure your keyboard (Optional) layout (mine is adapted to polish-programmer keyboard):

    nano /etc/vconsole.conf

    KEYMAP=pl
    FONT=Lat2-Terminus16
    FONTMAP=8859-2

    Run locale-gen for generate locales

    Set your hostname:

    nano /etc/hostname
     Write a name for your computer at this file and close it

    Create your user:

    useradd --create-home YOURNAME
    passwd YOURNAME

    Add your user to sudo:

     add to sudo user
    usermod --append --groups wheel YOURNAME
    
     Config sudo
    EDITOR=nano visudo
    
    %wheel    ALL=(ALL) ALL  Uncomment this line

    Enable some systemd units:

     if you want system auto connect to wireless network at startup
    systemctl enable iwd
     if you want system auto get ip at startup
    systemctl enable dhcpcd

    Creating Unified Kernel Image and configuring boot entry

    Create dracut scripts that will hook into pacman:

    nano /usr/local/bin/dracut-install.sh  copy this file to usb2

    Write:

    !/usr/bin/env bash
    
    mkdir -p /boot/efi/EFI/Linux
    
    while read -r line; do
        if [[ "$line" == 'usr/lib/modules/'+([^/])'/pkgbase' ]]; then
            kver="${line'usr/lib/modules/'}"
            kver="${kver%'/pkgbase'}"
    
            dracut --force --uefi --kver "$kver" /boot/efi/EFI/Linux/bootx64.efi
        fi
    done

    And the removal script:

    nano /usr/local/bin/dracut-remove.sh copy this file to usb2

    !/usr/bin/env bash
    rm -f /boot/efi/EFI/Linux/bootx64.efi

    Make those scripts executable and create pacman’s hook directory:

    chmod +x /usr/local/bin/dracut-
     mkdir /etc/pacman.d/hooks

    Now the actual hooks, first for the install and upgrade:

    nano /etc/pacman.d/hooks/90-dracut-install.hook  copy this file to usb2
    
    
    [Trigger]
    Type = Path
    Operation = Install
    Operation = Upgrade
    Target = usr/lib/modules//pkgbase
    
    [Action]
    Description = Updating linux EFI image
    When = PostTransaction
    Exec = /usr/local/bin/dracut-install.sh
    Depends = dracut
    NeedsTargets

    And for removal:

    nano /etc/pacman.d/hooks/60-dracut-remove.hook  copy this file to usb2
    
    
    [Trigger]
    Type = Path
    Operation = Remove
    Target = usr/lib/modules//pkgbase
    
    [Action]
    Description = Removing linux EFI image
    When = PreTransaction
    Exec = /usr/local/bin/dracut-remove.sh
    NeedsTargets

    Check UUID of your encrypted volume and write it to file you will edit next:

     if you wnat copy this file from usb => first copy it and then run this command:
    blkid -s UUID -o value /dev/nvme0n1p2 >> /etc/dracut.conf.d/cmdline.conf 
     and replace YOURUUID in this file with end line at this file (contain a code)

    Edit the file and fill with with kernel arguments:

    nano /etc/dracut.conf.d/cmdline.conf  copy this file to usb2
    
    
    kernelcmdline="rd.luks.uuid=luks-YOURUUID rd.lvm.lv=vg/root rd.lvm.lv=vg/swap resume=/dev/mapper/vg-swap root=/dev/mapper/vg-root rootfstype=ext4 rootflags=rw,relatime"

    Create file with flags:

    nano /etc/dracut.conf.d/flags.conf  copy this file to usb2
    
    
    compress="zstd"
    hostonly="no"

    Generate your image by re-installing linux package and making sure the hooks work properly:

    pacman -S linux

    You should have bootx64.efi within your /boot/efi/EFI/Linux/

    Now you only have to add UEFI boot entry and create an order of booting:

    efibootmgr  to see your status of boot
     Create boot entry for arch
    efibootmgr --create --disk /dev/nvme0n1 --label "Linux Boot Manager" --loader 'EFI\Linux\bootx64.efi' --unicode
    efibootmgr          Check if you have left over UEFI entries, remove them with efibootmgr -b INDEX -B and note down Arch index
    efibootmgr -o ARCHINDEXFROMPREVIOUSCOMMAND  0 or whatever number your Arch entry shows as

    Now you can reboot and log into your system. (if not boot to arch you can boot from usb againg and just open encrypted device and mount your created partiton and run arch-chroot for troubleshooting and check files and scripts)

    :exclamation: :exclamation: :exclamation: Compatilibity thing I noticed :exclamation: :exclamation: :exclamation:

    Some (older?) platforms can ignore entries by efibootmgr all together and just look for EFI\BOOT\bootx64.efi, in that case you may generate your UKI directly to that directory and under that name. It’s very important that the name is also bootx64.efi.

    SecureBoot

    At this point you should enable Setup Mode for SecureBoot in your BIOS, and erase your existing keys (it may spare you setting attributes for efi vars in OS). If your system does not offer reverting to default keys (useful if you want to install windows later), you should backup them, though this will not be described here.

    Configuring SecureBoot is easy with sbctl:

    pacman -S sbctl

    Check your status, setup mode should be enabled (You can do that in BIOS):

    sbctl status
      Installed:      ✘ Sbctl is not installed
      Setup Mode:     ✘ Enabled
      Secure Boot:    ✘ Disabled

    Create keys and sign binaries:

    sbctl create-keys
    sbctl sign -s /boot/efi/EFI/Linux/bootx64.efi it should be single file with name verying from kernel version

    Configure dracut to know where are signing keys:

    nano /etc/dracut.conf.d/secureboot.conf  copy this file to usb2
    
    
    uefisecurebootcert="/var/lib/sbctl/keys/db/db.pem"
    uefisecurebootkey="/var/lib/sbctl/keys/db/db.key"

    We also need to fix sbctl’s pacman hook. Creating the following file will overshadow the real one:

    nano /etc/pacman.d/hooks/zz-sbctl.hook  copy this file to usb2
    
    
    [Trigger]
    Type = Path
    Operation = Install
    Operation = Upgrade
    Operation = Remove
    Target = boot/
    Target = efi/
    Target = usr/lib/modules//vmlinuz
    Target = usr/lib/initcpio/
    Target = usr/lib//efi/.efi
    
    [Action]
    Description = Signing EFI binaries...
    When = PostTransaction
    Exec = /usr/bin/sbctl sign /boot/efi/EFI/Linux/bootx64.efi

    Enroll previously generated keys (drop microsoft option if you don’t want their keys – Ex. Usage: dual booting):

    sbctl enroll-keys --microsoft
    or use it's(without microsoft config secureboot):
    sbctl enroll-keys

    Reboot the system. Enable only UEFI boot and Secure boot in BIOS and set BIOS password so anyone won’t simply turn off the setting. If everything went fine you should first of all, boot into your system, and then verify with sbctl or bootctl:

    sbctl status
      Installed:    ✓ sbctl is installed
      Owner GUID:    YOURGUID
      Setup Mode:    ✓ Disabled
      Secure Boot:    ✓ Enabled

    Enroll LUKS key in TPM 🤩 – Optional but fascination

    if you wnat your computer boot without password (just with your config) do:

     Install tpm2-tools:
    pacman -S tpm2-tools

    Enroll your LUKS volume to tpm, simply run the following command as root:

     Select 0 or 1 or 2 or ... - My suggestin 1 < YOURREGNUMBER
    systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+1+2+3+4+5+7+8 /dev/nvme0n1p2

    or if you wnat remove your key, run this command:

    systemd-cryptenroll --wipe-slot=tpm2 /dev/nvme0n1p2

    You will need to add a kernel argument for enable the TPM2 bits

    open:

    nano /etc/dracut.conf.d/cmdline.conf

    and change to:

    kernelcmdline="rd.luks.options=YOURUUID=tpm2-device=auto rd.luks.uuid=luks-YOURUUID rd.lvm.lv=vg/root rd.lvm.lv=vg/swap resume=/dev/mapper/vg-swap root=/dev/mapper/vg-root rootfstype=ext4 rootflags=rw,relatime"

    Ensure that dracut builds in the TPM2 libraries. Create:

    nano /etc/dracut.conf.d/tpm2-tss.conf

    write:

    adddracutmodules+=" tpm2-tss "

    Finally, rebuild your unified kernel image:

     Run for auto
    pacman -S linux
     Mybe not neeed bellow command (Because this create a other xxxx.efi boot file) - Manually create
    ls /lib/modules  for check kver
    dracut --force --uefi --kver "YOURKEYVER" /boot/efi/EFI/Linux/bootx64.efi

    Additionally, A useful script to have handy for when you change UEFI settings to reenroll your LUKS key under the different PCR values is as follows:

    nano /bin/luksreenrolltpm

    write:

    systemd-cryptenroll --wipe-slot=tpm2 /dev/disk/by-uuid/UUIDHERE
     Select 0 or 1 or 2 or ... - My suggestin 1 < YOURREGNUMBER
    systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+1+2+3+4+5+7+8 /dev/disk/by-uuid/UUIDHERE

    At the end – you have a Compter with enabled Secure boot and encrypted drive

    When need passphrase at boot

    The goal here is to only require the passphrase when something spooky happens in your boot path.

    UEFI settings change? Request password.

    Some weird swap of some module of UEFI code that lives on your motherboard somewhere? Request password.

    Unified Kernel Image changes? Don’t even boot.

    Drive in another computer? Request password.

    The only time the drive should unlock is when it’s in the right computer with the right configuration and the right signed unified kernel image with the right kernel arguments. If your Xorg server just auto logs in and opens a terminal well…don’t do that.

    Thanks from

    Ataraxxia for secure-arch

    Krin for TPM2 unlocking

    this gist just a fork (copy this file from github to gist) wtih some additonal setting and edit and … for my usage

    if you want continue and install sway UI and some app and customaization go to secure-arch

    Thank you for reading this gist and i’m sorry about my english grammer (if it’s)

    https://gist.github.com/jvdi/bdc5066a75b53d8349ac7a73f5510f62
  • dockerizeWireguardOverWebsocket

    Set Up a dockerize Wireguard VPN Server over WebSocket Tunneling

    This tutorial good for Linux or Unix system at the end need to run bash script for connect
    (Also it’s have some technic for use in windows – Explained at client install section.)

    VPS => virtual private server as wiregurd vpn server

    Requirements

    • Assuming the firewall is off (Not Secure – it’s just for test so in production: config firewall)
    • VPS have docker and docker-compose (for install instrucrion : docker site full explained)
    • In VPS enable net.ipv4.ip_forward=1 at /etc/sysctl.conf (or /etc/sysctl.d/99-sysctl.conf) and reboot your system
    • Have access to root user in VPS
    • replace:
      • sub.domain.com : your favorit domain for this service
      • your_email@mailserver.com : your email for cert Install Wireguard at VPS by docker version: "2.1" services: wireguard: image: lscr.io/linuxserver/wireguard:latest container_name: wireguard cap_add: - NET_ADMIN - SYS_MODULE #optional environment: - PUID=1000 - PGID=1000 - TZ=Asia/Tehran - SERVERURL=auto #optional - SERVERPORT=51820 #optional - PEERS=peer1,peer2 #optional - PEERDNS=8.8.4.4,8.8.8.8 #optional - ALLOWEDIPS=0.0.0.0/0 #optional volumes: - ~/projects/wireguard/config:/config - /lib/modules:/lib/modules #optional ports: - 51820:51820/udp sysctls: - net.ipv4.conf.all.src_valid_mark=1 restart: unless-stopped
        Save to: docker-compose.yml
        and move to: /root/projects/wireguard/
        and in /root/projects/wireguard/ run : docker-compose up -d Install wstunnel by docker in VPS docker run --network host -d -e COMMAND="/usr/local/bin/wstunnel -v --server ws://0.0.0.0:33344 --restrictTo=127.0.0.1:51820" --name wstunnel --restart unless-stopped javidi/wstunnel Get free Cert for your domain by docker in VPS docker run --rm -p 80:80 -p 443:443 -v ~/projects/certs:/etc/letsencrypt certbot/certbot certonly -d sub.domain.com --standalone -m your_email@mailserver.com --agree-tos Install nginx for revese proxy by docker in VPS server { server_name sub.domain.com; listen 443 ssl; # Only allow access if the host is correct if ( $host != "sub.domain.com" ){ return 444; #CONNECTION CLOSED WITHOUT RESPONSE } ssl on; ssl_certificate /etc/nginx/certs/sub.domain.com/fullchain1.pem; ssl_certificate_key /etc/nginx/certs/sub.domain.com/privkey1.pem; location / { return 404; } location /svmvvvhDqtyd54zsP/ { proxy_pass http://172.17.0.1:33344; #host ip in docker network (if you not use docker nginx - use 127.0.0.1) proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_connect_timeout 10m; proxy_send_timeout 10m; proxy_read_timeout 90m; send_timeout 10m; } }
        Save to: sub.domain.com.conf
        and move to: /root/projects/nginx/
        and run : # Crete a network for other service docker network create ngx-rev # Run nginx server for Reverse-Proxy docker run --net ngx-rev -itd -v ~/projects/nginx:/etc/nginx/conf.d -v ~/projects/certs/archive/:/etc/nginx/certs/ -p 80:80 -p 443:443 --name ngx-rev-proxy --restart=unless-stopped nginx

    So in the Client 🎆:

    Install Wireguard in Client

    • Linux : sudo apt install wireguard-tools
    • Mac : brew install wireguard-tools (Like Ubuntu)
    • Windows : Download setup file of wireguard client for windows from Wireguard website

    Install WebSocket Tunnel on Client (Windows > 8):

    1.Enable (preup and postup and postdown) script in wireguad:

    - open cmd as admin in your windows<br/>
    - run:<br/>
      - `reg add HKLM\Software\WireGuard /v DangerousScriptExecution /t REG_DWORD /d 1 /f`<br/>
    

    2.Add Your host Custom IP (optional – if you need) – fill detail and add this text to end of hosts file of windows in c:\Windows\System32\Drivers\etc\hosts:

    
    # Added by Wg Over WS-Tunnel
    ws-server-ip_OR_cdn-server-ip yourdomain.com
    # End of section
    

    3.Create “WireGuardWS-Tunnel” folder in “C:\” (root of drive C)
    download needed tools:

    for /f %%g in (‘powershell -Command “(Get-NetRoute -DestinationPrefix ‘0.0.0.0/0’).NextHop”‘) do set DefaultGateway=%%g for /f “tokens=2” %%i in (‘nslookup %1 ^| findstr /C:”Address”‘) do set IPAddress=%%i

    :: add_route_to_main_gway_for_tunnel route add %IPAddress% mask 255.255.255.255 %DefaultGateway% C:\WireGuardWS-Tunnel\nssm.exe start “WireGuardWS-Tunnel”

    
    - Create `PostDown.bat` file in `C:\WireGuardWS-Tunnel`:
    

    @echo off

    for /f %%g in (‘powershell -Command “(Get-NetRoute -DestinationPrefix ‘0.0.0.0/0’).NextHop”‘) do set DefaultGateway=%%g for /f “tokens=2” %%i in (‘nslookup %1 ^| findstr /C:”Address”‘) do set IPAddress=%%i

    C:\WireGuardWS-Tunnel\nssm.exe stop “WireGuardWS-Tunnel” :: del_route_to_main_gway_for_tunnel route delete %IPAddress% mask 255.255.255.255 %DefaultGateway%

    4.run cmd in `"C:\WireGuardWS-Tunnel"` `[`with this command `cd C:\WireGuardWS-Tunnel`` ]` directory and enter:<br/>
        - `.\nssm.exe install "WireGuardWS-Tunnel"`<br/>
    5.in new opened window - set:<br/>
        - Path: `C:\WireGuardWS-Tunnel\wstunnel.exe`<br/>
            - Start directory: `C:\WireGuardWS-Tunnel`<br/><br/>
        - Argument: <br/>
        ```--quiet --udpTimeoutSec -1 --upgradePathPrefix "ENTER_YOUR_NGINX_PREFIX" --udp  -L 127.0.0.1:51820:127.0.0.1:51820 wss://yourdomain.com:443```<br/>
        - Arg for wstunnel-v7.9.0:<br/>
        ```client  --log-lvl OFF --tls-verify-certificate --tls-sni-override yourdomain.com --http-upgrade-path-prefix "ENTER_YOUR_NGINX_PREFIX"  -L udp://127.0.0.1:51820:127.0.0.1:51820?timeout_sec=0 wss://yourdomain.com:443```<br/><br/>
        - In Detail tab -> Startup type: Manual and Display name: `WireGuard WS-Tunnel`<br/>
    6.Click on: Install service<br/>
    7.open wireguard client and Import your wireguard config file (get config from wireguard server)<br/>
    7.In Wireguard client click on your connection and click on edit connecton:<br/>
        - set(write this line in connection)<br/>
      - get ip of yor domain by `ping yourdomain.com` command in cmd and get default gateway by `ipconfig` command in cmd:<br/>
    
      PreUp = "C:\WireGuardWS-Tunnel\PreUp.bat YOUR_DOMAIN"
      PostDown = "C:\WireGuardWS-Tunnel\PostDown.bat YOUR_DOMAIN"
      ```
    - uncheck Block untunneled traffic (kill-switch) in wireguard gui<br/>
    - Clock on: Save<br/>
    

    7.Click on Connect

    Install WebSocket Tunnel on Client (Linux):


    if you not have resolvconf run:

    • ubuntu : sudo apt install resolvconf
    wget https://github.com/erebe/wstunnel/releases/download/v5.0/wstunnel-linux-x64
    # if you get a zip file - extract it with unzip command then continue
    # maybe name in next versions change
    sudo mv wstunnel-linux-x64 /usr/local/bin/wstunnel
    sudo chmod +x /usr/local/bin/wstunnel
    

    Get this bash script for automation run Tunneling befor wireguard and down next (wireguard down) and …

    wget https://raw.githubusercontent.com/jvdi/wireguard-over-wss/patch-1/wstunnel.sh
    sudo mv wstunnel.sh /etc/wireguard/wstunnel.sh
    sudo chmod +x /etc/wireguard/wstunnel.sh
    

    Get wg Client Config from server

    scp root@VPS-ip:/root/projects/wireguard/config/peer_peer1/peer_peer1.conf ~/
    then sudo mv ~/peer_peer1.conf /etc/wireguard/wg0.conf and change end point ip in /etc/wireguard/wg0.conf like this:

    [Interface]
    Address = 10.13.13.2 # not change
    PrivateKey = ... # not change
    # ListenPort = 51820 # remove -- just delete this line or set this line as a comment 
    DNS = 8.8.4.4,8.8.8.8 # not change
    
    Table = off # add
    PreUp = source /etc/wireguard/wstunnel.sh && pre_up %i # add
    PostUp = source /etc/wireguard/wstunnel.sh && post_up %i # add
    PostDown = source /etc/wireguard/wstunnel.sh && post_down %i # add
    
    [Peer]
    PublicKey = ... # not change
    PresharedKey = ... # not change
    Endpoint = 127.0.0.1:51820 # chnage to it
    AllowedIPs = 0.0.0.0/0 # not change
    

    Create the wstunnel configuration file for shell script

    REMOTE_HOST=sub.domain.com
    REMOTE_PORT=51820
    UPDATE_HOSTS='/etc/hosts'
    WS_PREFIX='svmvvvhDqtyd54zsP' #Set in nginx conf
    # other config like change port or ... in script's doc
    

    and save to : /etc/wireguard/wg0.wstunnel

    If use CDN

    add : REMOTE_IP="0.1.2.3" # set a ip of your cdn (for find ip -> ping your cdn domain) :) in the end of /etc/wireguard/wg0.wstunnel

    Start WireGuard

    sudo wg-quick up wg0

    Stop WireGuard

    sudo wg-quick down wg0
    البته پیشنهاد میکنم از همون بالا با راهنمای انگلیسی پیش برید
    آموزش فارسی (منبع در زیر ذکر شده – با تشکر فراوان از نویسنده اصلی – من فقط داکر چسباندم بهش و بنظر خودم بعضی جاهاشو تغییر دادم بهتر بشه)

    CDN

    خب اول یک دامنه یا ساب دامنه انتخاب کنید و یک A رکورد به مقدار آی پی سرور خارجی و پرت HTTPS بسازید. سی دی ان داخلی باشه، باید روی آن ابر یا SSL , Proxy یا رمزنگاری رو فعال کنید تا ترافیک هم رمز بشه و هم از سرور هاش عبور کنه تا سرعت بهتر بشه (و ترجیحا اتصال مستقیم به سرور نباشه)

    SSL

    خب برای اون دامنه باید اس اس ال داشته باشید با این فایل ها fullchain.pem, privkey.pem, chain.pem, dhparam.pem آموزش گرفتن اس اس ال هم که زیاده. (dhparam- Diffie–Hellman (D-H))

    من قانع نشدم از dhparam استفاده کنم همون fullchain و privkey هم کفایت میکنه – با یه دستور ساده داکر در بالا تو ضیح داده شده که چطور ssl بگیرید

    WireGuard Server

    wget https://git.io/wireguard -O wireguard-install.sh && bash wireguard-install.sh

    کافیه این اسکریپت رو روی سرور ران کنید و بوم. با wg0.confسرور کاری نداریم. ولی فایل کانفیگ که برای کلاینت میسازه رو باید تغییر بدیم مختصر – پیشنهاد من استفاده از نسخه داکر وایرگارد هست – خیلی بهتره

    NGINX

    کانفیگ nginx در بالا آورده شده

    • مسیر فایل های اس اس ال رو درست کنیدClient.conf فایل کلاینت بعد از تغییر همچین چیزی میشه. “` [Interface] Address = 10.10.1.2/24 DNS = 8.8.8.8, 8.8.4.4اگر از نسخه داکر استفاده کنید یه listenport داره اونو حذف کنید <= این ۴خط هم اضافه میشه => Table = off PreUp = source /etc/wireguard/wstunnel.sh && pre_up %i PostUp = source /etc/wireguard/wstunnel.sh && post_up %i PostDown = source /etc/wireguard/wstunnel.sh && post_down %i

    PrivateKey = ….

    [Peer] PublicKey = …. PresharedKey = …. AllowedIPs = 0.0.0.0/0, ::/0 Endpoint = 127.0.0.1:51820 # <= این از آی پی سرور تغییر میکنه به لوکال PersistentKeepalive = 25

    ## Wstunnel Server
    - به آدرس زیر میرید و نسخه مربوطه هم برای سرور و کلاینت رو دانلود میکنید(در بالا یه نسخه داکر هم من ساختم براش)
      - `https://github.com/erebe/wstunnel/releases/`
    

    wget https://github.com/erebe/wstunnel/releases/download/v4.1/wstunnel-x64-linux mv wstunnel-x64-linux /usr/local/bin/wstunnel chmod uo+x /usr/local/bin/wstunnel setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/wstunnel

    ## Wstunnel Service in Server
    - یک فایل سرویس سیستم دی در مسیر زیر و محتویات پایین درست میکنید
      - `/etc/systemd/system/wstunnel.service`
    

    [Unit] Description=Tunnel WG UDP over websocket After=network.target

    [Service] Type=simple User=nobody ExecStart=/usr/local/bin/wstunnel -q –server ws://127.0.0.1:33344 –restrictTo=127.0.0.1:51820 Restart=no

    [Install] WantedBy=multi-user.target

    - 33344: همون پورتی که برای کانفیگ nginx انتخاب کردید
    - 51820: پورت دیفالت وایرگارد.اگه تغییر دادید هرجایی این پورت بود توی تنظیمات عوضش کنید
    
    سرویس رو با دستور زیر اجرا میکنید و وب سوکت راه میوفته
    `sudo systemctl enable --now wstunnel.service`
    چک کنید سرویس درست راه اندازی شده باشه
    `sudo systemctl status wstunnel.service`
    
    ## Enable IP Forward
    توی فایل زیر قسمت `net.ipv4.ip_forward=1` رو از حالت کامنت خارج کنید و سرور رو ریستارت کنید.
    - `/etc/sysctl.d/99-sysctl.conf`
    ## Client Side
    ### wg-quick
    برای وصل شدن به وایرگارد باید این نصب بشه
    - Mac :  `brew install wireguard-tools`
    - Ubuntu: `sudo apt install wireguard`
    - windows: [Follow this instruction](#install-websocket-tunnel-on-client-windows--8)
    ### WireGuard Config
    اول با دسترسی روت این مسیرها رو ایجاد کنید
    - `/var/run/wireguard/`
    - `/etc/wireguard/`
    
    فایل client.conf که قبلا سرور برامون ساخته بود و ما تغییرش دادیم رو با اسم wg0.conf روی مسیر زیر میریزیم
    - `/etc/wireguard/wg0.conf`
    - `sudo bash -c "chown root wg0.conf && chmod 640 wg0.conf"`
    ### wstunnel
    برای کلاینت هم سوکت رو نصب میکنید.چک کنید نسخه ها آخری باشه.
    

    wget https://github.com/erebe/wstunnel/releases/download/v5.0/wstunnel-linux-x64

    if you get a zip file – extract it with unzip command then continue

    maybe name in next versions change

    sudo mv wstunnel-linux-x64 /usr/local/bin/wstunnel sudo chmod +x /usr/local/bin/wstunnel

    ### wg0.wstunnel
    فایل کانفیگ وب سوکت رو توی مسیر زیر با محتویات پایین میسازیم
    - `/etc/wireguard/wg0.wstunnel`
    

    REMOTE_HOST=yourdomain.com REMOTE_PORT=51820 UPDATE_HOSTS=’/etc/hosts’ WS_PREFIX=’E7m5vGDqryd55MMP’

    - yourdomain.com: همونی که گذاشتید پشت سی دی ان
    - E8m4vGDqrydhgfjlP: همون مسیر رندومه توی nginx
    
    ### wstunnel.sh
    این اسکریپت کارهای روتینگ رو انجام میده که کل ترافیک لازم ما از وایرگارد از داخل سوکت رد بشه.
    

    wget https://raw.githubusercontent.com/jvdi/wireguard-over-wss/patch-1/wstunnel.sh sudo mv wstunnel.sh /etc/wireguard/wstunnel.sh sudo chmod +x /etc/wireguard/wstunnel.sh `` فقط چون سرویس ما قراره پشت سی دی ان باشه یه کانفیگ به فایل/etc/wireguard/wg0.wstunnel` اضافه میکنیم

    • شما این خط رو کامنت میکنی
      • REMOTE_IP="0.1.2.3" # set a ip of your cdn (for find ip -> ping your cdn domain) :)
    • و در خط بالا آی پی سرور سی دی ان رو هارد کد کن (فقط آی پی باید آی پی سرور سی دی ان باشه با پینگ دامنه متصل به سی دی ان می توان آی پی پیدا کرد – اگر میخواهید از سی دی ان استفاده کنید)

    Start WireGuard

    sudo wg-quick up wg0

    Stop WireGuard

    sudo wg-quick down wg0

    یه توضیح کوچک

    اینکه این اسکریپت فقط برای آزمایش درست شده و حتی در نسخه ویندوزی هم چیزی نیست که به منظوره تجاری بشه استفاده کرد و اینکه من بگم این پروژه رو من از جاهای دیگه ای که منابعش رو در آخر همین نوشته ذکر کردم برداشتم و کامل ترش کردم و یه بخش هایی اضافه کردم و بهترش کردم و برام جالب بود که میشه اینکار رو کرد و اینکه چقدر کارایی میدهد.

    اگر شما حوصله داشتید – یعنی اگر خودم حوصله داشته باشم شاید یه روز با grpc هم پیاده سازیش کردم – موفق و پیروز باشید

    Notice

    This project for me just for fun (We have very faster way than Wireguard about ** 😊😁) – so it’s just a test for fun
    and i’m not goood in English grammar so … (thankyou for your patient)

    References

    https://gist.github.com/jvdi/913549b4e329b9382459033322bf393d
  • FlaskApp_Dockerfile.Dockerfile

    FROM tiangolo/uwsgi-nginx-flask
    
    COPY ./requirements.txt /app/requirements.txt
    
    RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
    
    COPY ./app /app
    https://gist.github.com/jvdi/9df30f2a9b69a1bd8dbc33aa89fe23be
  • rahkar-default-pos-chenger.py

    import os
    from dotenv import load_dotenv
    from pywinauto.application import Application
    
    load_dotenv()
    
    flag = True
    while(True):
        if flag:
            try:
                app = Application().connect(title="تسویه فاکتور")
                window = app.WindowsForms10Window8app0141b42a_r7_ad1
                window.ComboBox0.select(int(os.getenv('DEFAULT_POS')))
                flag = False
            except:
                pass
        else:
            try:
                app = Application().connect(title="تسویه فاکتور")
            except:
                flag = True
    https://gist.github.com/jvdi/d2f64fb66765de953d2718adbc649a12
  • web_browser_indexdb_example.js

    function my_func(id, nme, prc){
        // This works on all devices/browsers, and uses IndexedDBShim as a final fallback 
        var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;
    
        // Open (or create) the database
        var open = indexedDB.open("site_data");
    
        // Create the schema
        open.onupgradeneeded = function() {
            var db = open.result;
            var store = db.createObjectStore("cart", {keyPath: "id"});
            var index = store.createIndex("NameIndex", ["id",]);
        };
    
        open.onsuccess = function() {
            // Start a new transaction
            var db = open.result;
            var tx = db.transaction("cart", "readwrite");
            var store = tx.objectStore("cart");
            var index = store.index("NameIndex");
    
            // Query the data.1 - ADD
            var getId = store.get(id);
            getId.onsuccess = function() {
                if (typeof getId.result !== 'undefined') {
                    // console.log(getId.result.amount);  // => "amount"
                    var a = getId.result.amount
                    var b = a+=1
                    store.put({id: id, name: nme, price: prc, amount: b});
                    document.getElementById('amount-'+id).innerHTML = b;
                    header_qty = parseInt(document.getElementById("header-qty").innerHTML);
                    document.getElementById("header-qty").innerHTML = header_qty+=1;
                }else{
                    // Add some data
                    // store.put({id: 12345, name: {first: "John", last: "Doe"}, age: 42});
                    store.put({id: id, name: nme, price: prc, amount: 1});
                    document.getElementById('amount-'+id).innerHTML = 1;
                    a = parseInt(document.getElementById("header-qty").innerHTML);
                    document.getElementById("header-qty").innerHTML = a+=1;
                }
              
            // Query the data.2 - CHECK
            var getId = store.get(id);
            getId.onsuccess = function() {
                if (typeof getId.result !== 'undefined') {
                    // console.log(getId.result.amount);  // => "amount"
                    var a = getId.result.amount
                    document.getElementById('amount-'+id).innerHTML = a;
                }else{
                    document.getElementById('amount-'+id).innerHTML = 0;
                }
              
            // Query the data.3 - REMOVE
            var getId = store.get(id);
            getId.onsuccess = function() {
                if (typeof getId.result !== 'undefined') {
                    // console.log(getId.result.amount);  // => "amount"
                    var a = getId.result.amount
                    var b = a-=1
                    if (b <= 0) {
                        // alert("zero");
                        store.delete(id);
                        document.getElementById('amount-'+id).innerHTML = 0;
                        header_qty = parseInt(document.getElementById("header-qty").innerHTML);
                        document.getElementById("header-qty").innerHTML -= 1;
                    }else{
                        store.put({id: id, name: nme, price: prc, amount: b});
                        document.getElementById('amount-'+id).innerHTML = b;
                        header_qty = parseInt(document.getElementById("header-qty").innerHTML);
                        document.getElementById("header-qty").innerHTML -=1;
                    }
                }
              
            // Query the data.4 - GET-DATA
            store.openCursor().onsuccess = function(event) {
                var cursor = event.target.result;
                  if (cursor) {
                      const para1 = document.createElement("tr");
                      para1.setAttribute("id", "tr-"+cursor.value.id);
                      const element1 = document.getElementById("dynamic");
                      element1.appendChild(para1);
    
                      const para2 = document.createElement("td");
                      const node2 = document.createTextNode(cursor.value.name);
                      para2.appendChild(node2);
    
                      const para3 = document.createElement("td");
                      const node3 = document.createTextNode((cursor.value.amount)*(cursor.value.price));
                      para3.appendChild(node3);
    
                      const para4 = document.createElement("td");
                      const node4 = document.createTextNode(cursor.value.amount);
                      para4.setAttribute("id", "amount-"+cursor.value.id);
                      para4.appendChild(node4);
    
                      const para5 = document.createElement("td");
                      const node5 = document.createTextNode(cursor.value.price);
                      para5.appendChild(node5);
    
                      const para6 = document.createElement("td");
                      const node6 = document.createElement("img");
                      node6.setAttribute("src", "/static/shop/images/tools/remove.png");
                      node6.setAttribute("width", "20rem");
                      node6.setAttribute("onclick", "remove_product("+cursor.value.id+", '"+cursor.value.name+"', '"+cursor.value.price+"')");
                      para6.appendChild(node6);
    
                      const myelement = document.getElementById("tr-"+cursor.value.id);
                      myelement.appendChild(para2);
                      myelement.appendChild(para3);
                      myelement.appendChild(para4);
                      myelement.appendChild(para5);
                      myelement.appendChild(para6);
                      //document.write("Name for SSN " + cursor.key + " is " + cursor.value.id);
                      cursor.continue();
                  }
                  else {
                    // console.log("No more entries!");
                  }
            };
    
            // Close the db when the transaction is done
            tx.oncomplete = function() {
                db.close();
            };
        }
    }
    https://gist.github.com/jvdi/864e17e7cbbf7992577e075e022db0ff