From d1be8ebdca9280d1958a482e6454307b2ec5e642 Mon Sep 17 00:00:00 2001 From: dangerboot <> Date: Fri, 23 Jan 2026 08:55:18 +0100 Subject: [PATCH] .git broken, restart --- .gitignore | 10 + dock/alpine/Dockerfile | 20 + dock/alpine/docker-compose.yml | 14 + dock/arch/Dockerfile | 22 + dock/arch/docker-compose.yml | 16 + dock/librewolf/docker-compose.yml | 14 + dock/librewolf/run_librewolf.sh | 15 + git_to_group.sh | 9 + install/42.sh | 20 + install/alpine.sh | 29 + install/apk.sh | 18 + install/app.sh | 4 + install/apt.sh | 37 + install/arch.sh | 25 + install/arm_install.sh | 122 ++ install/chmod.sh | 14 + install/config.sh | 25 + install/debian.sh | 20 + install/fedora.sh | 14 + install/j.sh | 20 + install/network.sh | 5 + install/pacman.sh | 52 + install/python.sh | 16 + install/test | 29 + install/tree_cpy.sh | 10 + install/yay.sh | 6 + net/blacklist.txt | 38 + net/cidr_list.txt | 172 ++ net/nft_setup.sh | 85 + net/torrent_list.md | 336 ++++ net/virtnat.xml | 9 + net/whitelist.txt | 37 + usr/bin/alpine-arm-dd | 115 ++ usr/bin/alpine-qemu-install | 65 + usr/bin/alpine-qemu-run | 42 + usr/bin/append_cmd | 14 + usr/bin/arch-fstables | 9 + usr/bin/arch-qemu-install | 39 + usr/bin/archinstall | 11 + usr/bin/aur | 6 + usr/bin/basha | 28 + usr/bin/basha.obsolete | 12 + usr/bin/basha_obsolete | 12 + usr/bin/bashalias | 6 + usr/bin/bashrc | 6 + usr/bin/blacklist | 7 + usr/bin/brc | 11 + usr/bin/bs-dl-post | 17 + usr/bin/bsbrute.py | 73 + usr/bin/bscon.py | 63 + usr/bin/bsconn.py | 25 + usr/bin/bsdlfeed-light | 50 + usr/bin/bsdlfeeds.py | 72 + usr/bin/bsdlpost.py | 68 + usr/bin/bsdlprofile.py | 147 ++ usr/bin/bsgetdid.py | 28 + usr/bin/bsjson2html.py | 46 + usr/bin/bsky-get-did | 8 + usr/bin/bsloaduris.py | 54 + usr/bin/bspost.py | 20 + usr/bin/bsrdprofilebasic.py | 91 + usr/bin/bsreadjson.sh | 4 + usr/bin/bsreadprofile.py | 27 + usr/bin/bsurifromurl | 25 + usr/bin/bsurifromurl.py | 19 + usr/bin/bt-addr | 11 + usr/bin/bt-cheatsheet | 19 + usr/bin/bt-connect | 11 + usr/bin/catbin | 11 + usr/bin/cert-librewolf | 19 + usr/bin/cert-rsa | 15 + usr/bin/chroot-iso | 30 + usr/bin/clean-dict | 14 + usr/bin/clone | 13 + usr/bin/commit_if_modified | 20 + usr/bin/conn | 14 + usr/bin/debian_dl | 49 + usr/bin/dict-maker | 111 ++ usr/bin/expresso | 11 + usr/bin/expresso_stat.sh | 93 + usr/bin/find-bin | 11 + usr/bin/find-inode | 22 + usr/bin/gcl | 6 + usr/bin/git_list_heavy | 11 + usr/bin/git_list_heavy_commits | 6 + usr/bin/git_rm_repo | 7 + usr/bin/gitadd | 7 + usr/bin/gitaddcommit | 11 + usr/bin/gitea_deploy.sh | 33 + usr/bin/gitignore | 12 + usr/bin/gitlog | 6 + usr/bin/gitmain | 10 + usr/bin/gitotal | 10 + usr/bin/gnunet-push | 25 + usr/bin/graphene | 16 + usr/bin/grepip | 6 + usr/bin/grepips | 6 + usr/bin/grepkey | 19 + usr/bin/header_awk | 6 + usr/bin/header_journal | 16 + usr/bin/history_full | 13 + usr/bin/ipinfo | 6 + usr/bin/journal | 44 + usr/bin/journal-perso | 42 + usr/bin/keygen-repo | 37 + usr/bin/kill_all | 11 + usr/bin/lemmatizer.py | 27 + usr/bin/m | 15 + usr/bin/mediaspi | 21 + usr/bin/mobian_dl | 71 + usr/bin/monip | 6 + usr/bin/netstat_tunlp | 6 + usr/bin/nmap-http | 11 + usr/bin/nmap-list | 26 + usr/bin/nmap-port | 16 + usr/bin/nmap_full | 6 + usr/bin/nmap_sA | 6 + usr/bin/nmap_script.sh | 81 + usr/bin/nmap_ssh_brute | 6 + usr/bin/nmap_version | 7 + usr/bin/normi | 6 + usr/bin/p | 3 + usr/bin/pacmaninstall | 6 + usr/bin/portlsof | 8 + usr/bin/post-chroot-iso | 18 + usr/bin/ps_parents | 14 + usr/bin/py_test | 9 + usr/bin/qtileconf | 4 + usr/bin/refresh_time | 4 + usr/bin/report-cmd | 17 + usr/bin/report-ipv6 | 37 + usr/bin/report_crash | 30 + usr/bin/report_last_boot | 26 + usr/bin/rsa-sign | 7 + usr/bin/screen-double | 5 + usr/bin/sign-arch | 39 + usr/bin/sign-efi | 25 + usr/bin/sign-wiki | 36 + usr/bin/sortu | 6 + usr/bin/sound-down | 2 + usr/bin/sound-up | 2 + usr/bin/ss-greppb | 4 + usr/bin/status | 6 + usr/bin/tail-dl.sh | 31 + usr/bin/tcp-manual-scan | 46 + usr/bin/tcpd | 41 + usr/bin/to_mp3 | 12 + usr/bin/to_wav | 13 + usr/bin/usb-reset | 42 + usr/bin/vpn | 6 + usr/bin/vrc | 16 + usr/bin/whois_list | 23 + usr/bin/write-unprotect | 13 + usr/bin/wwan-del | 8 + usr/bin/wwan-setup | 18 + usr/etc/apk/repositories | 2 + usr/etc/env | 24 + usr/etc/iwd/main.conf | 2 + .../client/ca-free-4.protonvpn.tcp.ovpn | 123 ++ .../client/ch-free-2.protonvpn.tcp.ovpn | 123 ++ .../client/ch-free-6.protonvpn.tcp.ovpn | 123 ++ usr/etc/openvpn/client/client.conf | 10 + .../client/jp-free-33.protonvpn.tcp.ovpn | 123 ++ .../client/no-free-4.protonvpn.tcp.ovpn | 123 ++ .../client/us-free-74.protonvpn.tcp.ovpn | 123 ++ .../openvpn/scripts/update-systemd-resolved | 1524 +++++++++++++++++ usr/etc/openvpn/update-resolv-conf | 71 + usr/etc/resolv.conf | 4 + usr/etc/systemd/resolved.conf | 44 + usr/etc/systemd/system/tcpd.service | 12 + usr/etc/systemd/system/tcpd.sh | 10 + usr/etc/systemd/system/tcpd_bkup.sh | 21 + usr/home/.bash_aliases | 643 +++++++ usr/home/.bashrc | 142 ++ usr/home/.config/qtile/config.py | 237 +++ usr/home/.inputrc | 25 + usr/home/.profile | 1 + usr/home/.vim/.netrwhist | 9 + usr/home/.vim/templates/template.c | 19 + usr/home/.vim/templates/template.h | 0 usr/home/.vim/templates/template.my_aliases | 25 + usr/home/.vim/templates/template.py | 58 + usr/home/.vim/templates/template.sh | 25 + usr/home/.vim/templates/template.yaml | 12 + usr/home/.vimrc | 104 ++ usr/lib/systemd/system/nftables.service | 15 + usr/sbin/alpine-qemu-install | 63 + usr/sbin/arch-qemu-install | 39 + usr/sbin/basha | 28 + usr/sbin/basha-sudo | 28 + usr/sbin/blacklist | 6 + usr/sbin/brc | 11 + usr/sbin/cert-librewolf | 19 + usr/sbin/chroot-iso | 30 + usr/sbin/commit_if_modified | 20 + usr/sbin/gitaddcommit | 11 + usr/sbin/journalctl_prettyfy | 20 + usr/sbin/monte | 18 + usr/sbin/nft-list | 6 + usr/sbin/refresh_time | 4 + usr/sbin/sudoadd | 6 + usr/sbin/tcpd | 41 + usr/sbin/usb-reset | 42 + usr/sbin/vpn | 6 + usr/sbin/whitelist | 6 + usr/share/nmap/scripts/check-port.nse | 39 + 206 files changed, 8431 insertions(+) create mode 100644 .gitignore create mode 100644 dock/alpine/Dockerfile create mode 100644 dock/alpine/docker-compose.yml create mode 100644 dock/arch/Dockerfile create mode 100644 dock/arch/docker-compose.yml create mode 100644 dock/librewolf/docker-compose.yml create mode 100644 dock/librewolf/run_librewolf.sh create mode 100644 git_to_group.sh create mode 100755 install/42.sh create mode 100755 install/alpine.sh create mode 100755 install/apk.sh create mode 100755 install/app.sh create mode 100755 install/apt.sh create mode 100755 install/arch.sh create mode 100755 install/arm_install.sh create mode 100755 install/chmod.sh create mode 100755 install/config.sh create mode 100755 install/debian.sh create mode 100755 install/fedora.sh create mode 100755 install/j.sh create mode 100755 install/network.sh create mode 100755 install/pacman.sh create mode 100755 install/python.sh create mode 100755 install/test create mode 100755 install/tree_cpy.sh create mode 100755 install/yay.sh create mode 100644 net/blacklist.txt create mode 100644 net/cidr_list.txt create mode 100644 net/nft_setup.sh create mode 100644 net/torrent_list.md create mode 100644 net/virtnat.xml create mode 100644 net/whitelist.txt create mode 100755 usr/bin/alpine-arm-dd create mode 100755 usr/bin/alpine-qemu-install create mode 100755 usr/bin/alpine-qemu-run create mode 100755 usr/bin/append_cmd create mode 100755 usr/bin/arch-fstables create mode 100755 usr/bin/arch-qemu-install create mode 100755 usr/bin/archinstall create mode 100755 usr/bin/aur create mode 100755 usr/bin/basha create mode 100755 usr/bin/basha.obsolete create mode 100755 usr/bin/basha_obsolete create mode 100755 usr/bin/bashalias create mode 100755 usr/bin/bashrc create mode 100755 usr/bin/blacklist create mode 100755 usr/bin/brc create mode 100755 usr/bin/bs-dl-post create mode 100755 usr/bin/bsbrute.py create mode 100755 usr/bin/bscon.py create mode 100755 usr/bin/bsconn.py create mode 100755 usr/bin/bsdlfeed-light create mode 100755 usr/bin/bsdlfeeds.py create mode 100755 usr/bin/bsdlpost.py create mode 100755 usr/bin/bsdlprofile.py create mode 100755 usr/bin/bsgetdid.py create mode 100755 usr/bin/bsjson2html.py create mode 100755 usr/bin/bsky-get-did create mode 100755 usr/bin/bsloaduris.py create mode 100755 usr/bin/bspost.py create mode 100755 usr/bin/bsrdprofilebasic.py create mode 100755 usr/bin/bsreadjson.sh create mode 100755 usr/bin/bsreadprofile.py create mode 100755 usr/bin/bsurifromurl create mode 100755 usr/bin/bsurifromurl.py create mode 100755 usr/bin/bt-addr create mode 100755 usr/bin/bt-cheatsheet create mode 100755 usr/bin/bt-connect create mode 100755 usr/bin/catbin create mode 100755 usr/bin/cert-librewolf create mode 100755 usr/bin/cert-rsa create mode 100755 usr/bin/chroot-iso create mode 100755 usr/bin/clean-dict create mode 100755 usr/bin/clone create mode 100755 usr/bin/commit_if_modified create mode 100755 usr/bin/conn create mode 100755 usr/bin/debian_dl create mode 100755 usr/bin/dict-maker create mode 100755 usr/bin/expresso create mode 100755 usr/bin/expresso_stat.sh create mode 100755 usr/bin/find-bin create mode 100755 usr/bin/find-inode create mode 100755 usr/bin/gcl create mode 100755 usr/bin/git_list_heavy create mode 100755 usr/bin/git_list_heavy_commits create mode 100755 usr/bin/git_rm_repo create mode 100755 usr/bin/gitadd create mode 100755 usr/bin/gitaddcommit create mode 100755 usr/bin/gitea_deploy.sh create mode 100755 usr/bin/gitignore create mode 100755 usr/bin/gitlog create mode 100755 usr/bin/gitmain create mode 100755 usr/bin/gitotal create mode 100755 usr/bin/gnunet-push create mode 100755 usr/bin/graphene create mode 100755 usr/bin/grepip create mode 100755 usr/bin/grepips create mode 100755 usr/bin/grepkey create mode 100755 usr/bin/header_awk create mode 100755 usr/bin/header_journal create mode 100755 usr/bin/history_full create mode 100755 usr/bin/ipinfo create mode 100755 usr/bin/journal create mode 100755 usr/bin/journal-perso create mode 100755 usr/bin/keygen-repo create mode 100755 usr/bin/kill_all create mode 100755 usr/bin/lemmatizer.py create mode 100755 usr/bin/m create mode 100755 usr/bin/mediaspi create mode 100755 usr/bin/mobian_dl create mode 100755 usr/bin/monip create mode 100755 usr/bin/netstat_tunlp create mode 100755 usr/bin/nmap-http create mode 100755 usr/bin/nmap-list create mode 100755 usr/bin/nmap-port create mode 100755 usr/bin/nmap_full create mode 100755 usr/bin/nmap_sA create mode 100755 usr/bin/nmap_script.sh create mode 100755 usr/bin/nmap_ssh_brute create mode 100755 usr/bin/nmap_version create mode 100755 usr/bin/normi create mode 100755 usr/bin/p create mode 100755 usr/bin/pacmaninstall create mode 100755 usr/bin/portlsof create mode 100755 usr/bin/post-chroot-iso create mode 100755 usr/bin/ps_parents create mode 100755 usr/bin/py_test create mode 100755 usr/bin/qtileconf create mode 100755 usr/bin/refresh_time create mode 100755 usr/bin/report-cmd create mode 100755 usr/bin/report-ipv6 create mode 100755 usr/bin/report_crash create mode 100755 usr/bin/report_last_boot create mode 100755 usr/bin/rsa-sign create mode 100755 usr/bin/screen-double create mode 100755 usr/bin/sign-arch create mode 100755 usr/bin/sign-efi create mode 100755 usr/bin/sign-wiki create mode 100755 usr/bin/sortu create mode 100755 usr/bin/sound-down create mode 100755 usr/bin/sound-up create mode 100755 usr/bin/ss-greppb create mode 100755 usr/bin/status create mode 100755 usr/bin/tail-dl.sh create mode 100755 usr/bin/tcp-manual-scan create mode 100755 usr/bin/tcpd create mode 100755 usr/bin/to_mp3 create mode 100755 usr/bin/to_wav create mode 100755 usr/bin/usb-reset create mode 100755 usr/bin/vpn create mode 100755 usr/bin/vrc create mode 100755 usr/bin/whois_list create mode 100755 usr/bin/write-unprotect create mode 100755 usr/bin/wwan-del create mode 100755 usr/bin/wwan-setup create mode 100644 usr/etc/apk/repositories create mode 100644 usr/etc/env create mode 100644 usr/etc/iwd/main.conf create mode 100644 usr/etc/openvpn/client/ca-free-4.protonvpn.tcp.ovpn create mode 100644 usr/etc/openvpn/client/ch-free-2.protonvpn.tcp.ovpn create mode 100644 usr/etc/openvpn/client/ch-free-6.protonvpn.tcp.ovpn create mode 100644 usr/etc/openvpn/client/client.conf create mode 100644 usr/etc/openvpn/client/jp-free-33.protonvpn.tcp.ovpn create mode 100644 usr/etc/openvpn/client/no-free-4.protonvpn.tcp.ovpn create mode 100644 usr/etc/openvpn/client/us-free-74.protonvpn.tcp.ovpn create mode 100644 usr/etc/openvpn/scripts/update-systemd-resolved create mode 100644 usr/etc/openvpn/update-resolv-conf create mode 100644 usr/etc/resolv.conf create mode 100644 usr/etc/systemd/resolved.conf create mode 100644 usr/etc/systemd/system/tcpd.service create mode 100755 usr/etc/systemd/system/tcpd.sh create mode 100755 usr/etc/systemd/system/tcpd_bkup.sh create mode 100644 usr/home/.bash_aliases create mode 100644 usr/home/.bashrc create mode 100644 usr/home/.config/qtile/config.py create mode 100644 usr/home/.inputrc create mode 100644 usr/home/.profile create mode 100644 usr/home/.vim/.netrwhist create mode 100644 usr/home/.vim/templates/template.c create mode 100644 usr/home/.vim/templates/template.h create mode 100644 usr/home/.vim/templates/template.my_aliases create mode 100644 usr/home/.vim/templates/template.py create mode 100644 usr/home/.vim/templates/template.sh create mode 100644 usr/home/.vim/templates/template.yaml create mode 100644 usr/home/.vimrc create mode 100644 usr/lib/systemd/system/nftables.service create mode 100755 usr/sbin/alpine-qemu-install create mode 100755 usr/sbin/arch-qemu-install create mode 100755 usr/sbin/basha create mode 100755 usr/sbin/basha-sudo create mode 100755 usr/sbin/blacklist create mode 100755 usr/sbin/brc create mode 100755 usr/sbin/cert-librewolf create mode 100755 usr/sbin/chroot-iso create mode 100755 usr/sbin/commit_if_modified create mode 100755 usr/sbin/gitaddcommit create mode 100755 usr/sbin/journalctl_prettyfy create mode 100755 usr/sbin/monte create mode 100755 usr/sbin/nft-list create mode 100755 usr/sbin/refresh_time create mode 100755 usr/sbin/sudoadd create mode 100755 usr/sbin/tcpd create mode 100755 usr/sbin/usb-reset create mode 100755 usr/sbin/vpn create mode 100755 usr/sbin/whitelist create mode 100644 usr/share/nmap/scripts/check-port.nse diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8e754b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.config/Brav* +*.swp +.ssh/ +.ssh +*ssh +py-env/ +.ssh/* +passwd_gen +deb_dock/home_skel/.vim/.netrwhist +**/__pycache__/ diff --git a/dock/alpine/Dockerfile b/dock/alpine/Dockerfile new file mode 100644 index 0000000..6ef5aed --- /dev/null +++ b/dock/alpine/Dockerfile @@ -0,0 +1,20 @@ +FROM alpine:latest + +# Install base packages +RUN apk add \ + librewolf +# xorg-xhost \ +# dbus \ +# sudo \ +# mesa \ +# alsa-utils \ +# xorg-xprop \ +# pulseaudio + +RUN useradd -m -G wheel painain \ + && echo "%wheel ALL=(ALL) ALL, !/usr/bin/passwd root" >> /etc/sudoers + +USER painpain +WORKDIR /home/painpain + +#ENTRYPOINT [""] diff --git a/dock/alpine/docker-compose.yml b/dock/alpine/docker-compose.yml new file mode 100644 index 0000000..61c4377 --- /dev/null +++ b/dock/alpine/docker-compose.yml @@ -0,0 +1,14 @@ +services: + al-pine: + build: . + container_name: alp + environment: + - DISPLAY=${DISPLAY} # for GUI + volumes: + - ./shared-root:/shared-root + - ./extra-folder:/extra-folder + - /tmp/.X11-unix:/tmp/.X11-unix # X11 socket + network_mode: "host" # optional: allows GUI display directly + tty: true + stdin_open: true + diff --git a/dock/arch/Dockerfile b/dock/arch/Dockerfile new file mode 100644 index 0000000..5dc9192 --- /dev/null +++ b/dock/arch/Dockerfile @@ -0,0 +1,22 @@ +FROM archlinux:latest + +# Install base packages +RUN pacman -Syu --noconfirm \ + firefox +# xorg-xhost \ +# dbus \ +# sudo \ +# mesa \ +# alsa-utils \ +# xorg-xprop \ +# pulseaudio + +# Optional: create a user to avoid running as root +RUN useradd -m -G wheel painoain \ + && echo "archuser ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + +USER archuser +WORKDIR /home/archuser + +# Set Firefox as entrypoint +ENTRYPOINT ["firefox"] diff --git a/dock/arch/docker-compose.yml b/dock/arch/docker-compose.yml new file mode 100644 index 0000000..c0efff3 --- /dev/null +++ b/dock/arch/docker-compose.yml @@ -0,0 +1,16 @@ +version: "3.9" + +services: + arch-firefox: + build: . + container_name: arch_firefox + environment: + - DISPLAY=${DISPLAY} # for GUI + volumes: + - ./shared-root:/shared-root + - ./extra-folder:/extra-folder + - /tmp/.X11-unix:/tmp/.X11-unix # X11 socket + network_mode: "host" # optional: allows GUI display directly + tty: true + stdin_open: true + diff --git a/dock/librewolf/docker-compose.yml b/dock/librewolf/docker-compose.yml new file mode 100644 index 0000000..1050b0e --- /dev/null +++ b/dock/librewolf/docker-compose.yml @@ -0,0 +1,14 @@ +services: + librewolf: + image: lscr.io/linuxserver/librewolf:latest + container_name: librewolf + environment: + - PUID=1000 + - PGID=1000 + - TZ=Etc/UTC + volumes: + - /srv/appdata/librewolf/config:/config + ports: + - 3001:3001 + shm_size: "1gb" + restart: unless-stopped diff --git a/dock/librewolf/run_librewolf.sh b/dock/librewolf/run_librewolf.sh new file mode 100644 index 0000000..d3a7590 --- /dev/null +++ b/dock/librewolf/run_librewolf.sh @@ -0,0 +1,15 @@ +#!/usr/bin/bash + +# https://belginux.com/installer-librewolf-avec-docker/ +# +docker compose up -d + +# Rendez-vous sur l'ip:# port, +# suivant l'IP de votre serveur local et du port choisi, +# 3000 par défaut: +# +# http://ip:3004/ +# +# En HTTPS: +# +# https://ip:3001/ diff --git a/git_to_group.sh b/git_to_group.sh new file mode 100644 index 0000000..212c4cd --- /dev/null +++ b/git_to_group.sh @@ -0,0 +1,9 @@ +#!/usr/bin/bash + +REPO=${1:-"svr"} +# make the repository shared +git config core.$REPO group # or whatever other sharing option +# fix the setgid bit +find . -type d | xargs chmod g+s +# repair the permissions +chmod -R g+r * diff --git a/install/42.sh b/install/42.sh new file mode 100755 index 0000000..3ac2aa6 --- /dev/null +++ b/install/42.sh @@ -0,0 +1,20 @@ +#!/usr/bin/bash +MACHINE_DIR="$HOME/machine" + +FILES_TO_LINK="$MACHINE_DIR/.vim $MACHINE_DIR/.vimrc $MACHINE_DIR/.bashrc $MACHINE_DIR/.bash_aliases" +for F in $FILES_TO_LINK; do + BASENAME=$(basename $F) + mv $HOME/$BASENAME $HOME/$BASENAME.original + ln -s $F $HOME/$BASENAME +done; + +#chsh -s /usr/bin/bash +#echo '. ~/.bash_aliases' >> $HOME/.zshrc +#echo '. ~/.bashrc' >> $HOME/.zshrc +bash apt_install.sh +python3 -m pip install --upgrade pip setuptools +python3 -m pip install norminette + +git clone https://github.com/cacharle/c_formatter_42 +cd c_formatter_42 +pip3 install -e . diff --git a/install/alpine.sh b/install/alpine.sh new file mode 100755 index 0000000..737a627 --- /dev/null +++ b/install/alpine.sh @@ -0,0 +1,29 @@ +#!/usr/bin/bash + +#if [[ "$EUID" -ne "0" ]]; then +# echo "This script must be run as root" +# exit 1 +#fi + +# append sources +H=$(find / -type d -name home | head -1) +source $H/.bashrc +bash tree_cpy.sh $MACHINE_DIR/usr +bash config.sh +bash python.sh + +bash chmod.sh +# append sources + +bash apk.sh + +bash network.sh +#systemctl enable --now NetworkManager #enable dongle + +#pacman --noconfirm -Syu ulogd +#NETWORKDIR="$MACHINE_DIR/networking" +##TOR_LIST=$NETWORKDIR/tor_list.txt +##curl https://www.dan.me.uk/torlist/?full= > $TOR_LIST +#systemctl enable ulogd +#systemctl start ulogd +#bash $NETWORKDIR/iptables_script.sh -f $NETWORKDIR/ip_to_ban.txt -r diff --git a/install/apk.sh b/install/apk.sh new file mode 100755 index 0000000..cd75af5 --- /dev/null +++ b/install/apk.sh @@ -0,0 +1,18 @@ +#!/usr/bin/bash + +#if [ "$UEID" -ne "0" ] ; then +# echo "This script must be run as root" +#fi + +apk add git +apk add nftables +apk add tcpdump +apk add make +apk add whois +apk add nmap +apk add man-db +apk add vim +apk add git-filter-repo + + + diff --git a/install/app.sh b/install/app.sh new file mode 100755 index 0000000..bfc329d --- /dev/null +++ b/install/app.sh @@ -0,0 +1,4 @@ +#!/usr/bin/bash + +wget https://github.com/obsidianmd/obsidian-releases/releases/download/v1.9.14/Obsidian-1.9.14.AppImage + diff --git a/install/apt.sh b/install/apt.sh new file mode 100755 index 0000000..d158531 --- /dev/null +++ b/install/apt.sh @@ -0,0 +1,37 @@ +#!/usr/bin/bash + +#apt install -y ufw +#curl -fsS https://dl.brave.com/install.sh | sh + + +apt install -y bc +apt install -y virt-viewer +apt install -y gawk +apt install -y exuberant-ctags +apt install -y cmake +apt install -y unzip +apt install -y tcpdump +apt install -y moreutils +apt install -y net-tools +apt install -y make +apt install -y whois +apt install -y nmap +apt install -y lldb +apt install -y man-db +apt install -y gdb +apt install -y docker +apt install -y makepkg +apt install -y vim +apt install -y gcc +apt install -y make +apt install -y pip +apt install -y curl +apt install -y tree +apt install -y ffmpeg +#apt install -y vlc +#apt install -y terminator +#apt install -y gimp +#apt install -y redshift +#apt install -y snap +#curl -fsSL "https://windsurf-stable.codeiumdata.com/wVxQEIWkwPUEAGf3/windsurf.gpg" | sudo gpg --dearmor -o /usr/share/keyrings/windsurf-stable-archive-keyring.gpg +#echo "deb [signed-by=/usr/share/keyrings/windsurf-stable-archive-keyring.gpg arch=amd64] https://windsurf-stable.codeiumdata.com/wVxQEIWkwPUEAGf3/apt stable main" | sudo tee /etc/apt/sources.list.d/windsurf.list > /dev/null diff --git a/install/arch.sh b/install/arch.sh new file mode 100755 index 0000000..a10af0c --- /dev/null +++ b/install/arch.sh @@ -0,0 +1,25 @@ +#!/usr/bin/bash + +if [[ "$EUID" -ne "0" ]]; then + echo "This script must be run as root" + exit 1 +fi + +if [ $# -ne 1 ] ; then + echo usage $0 MACHINE_DIR + exit 0 +fi +MACHINE_DIR=${1:-"svr"} + +bash tree_cpy.sh $MACHINE_DIR/usr +# append sources +bash config.sh +source /home/.bashrc +bash python.sh +source /home/.bashrc + +bash chmod.sh + +bash pacman.sh + +bash network.sh diff --git a/install/arm_install.sh b/install/arm_install.sh new file mode 100755 index 0000000..6b1e13d --- /dev/null +++ b/install/arm_install.sh @@ -0,0 +1,122 @@ +#!/usr/bin/bash + +set -euo pipefail + +cleanup() { + set +e + umount -l "$MOUNT_DIR/dev" "$MOUNT_DIR/sys" "$MOUNT_DIR/proc" 2>/dev/null + umount -l "$MOUNT_DIR/boot" "$MOUNT_DIR" 2>/dev/null + [ -n "${LOOPDEV:-}" ] && losetup -d "$LOOPDEV" 2>/dev/null +} +trap cleanup EXIT + + +IMG_URL="https://downloads.raspberrypi.org/raspios_lite_armhf_latest" +IMG_FILE="raspios_lite.img" +COMPR_IMG="raspios_lite.img.xz" +MOUNT_DIR="/mnt/rpi" +SSH_PORT=888 +WIFI_SSID="$1" +WIFI_PASS="$2" +ROOT_PASS="$3" + +if [ ! -e $IMG_FILE ] ; then + if [ ! -e $COMPR_IMG ] ; then + wget -O ${COMPR_IMG} "$IMG_URL" + wget -O "${IMG_FILE}.sha256" "${IMG_URL}.sha256" + cd $(dirname "$IMG_FILE") + sha256sum -c "${COMPR_IMG}.sha256" --status + if [ $? -ne 0 ]; then + echo "SHA256 mismatch ! Aborting." + exit 1 + else + echo "shasum ok" + fi + cd - + fi + unxz -f "$COMPR_IMG" +fi + +apt-get install qemu-user-static binfmt-support +cp /usr/bin/qemu-arm-static $MOUNT_DIR/usr/bin/ + +# 2. Associer l’image à un loop device +LOOPDEV=$(losetup --find --partscan --show "$IMG_FILE") +BOOTPART="${LOOPDEV}p1" +ROOTPART="${LOOPDEV}p2" + +parted --script "$LOOPDEV" resizepart 2 100% +e2fsck -f -y "$ROOTPART" +resize2fs "$ROOTPART" + +mkdir -p "$MOUNT_DIR" +mount "$ROOTPART" "$MOUNT_DIR" +mount "$BOOTPART" "$MOUNT_DIR/boot" + +mount --bind /dev "$MOUNT_DIR/dev" +mount --bind /sys "$MOUNT_DIR/sys" +mount --bind /proc "$MOUNT_DIR/proc" +cp /etc/resolv.conf "$MOUNT_DIR/etc/" + +chroot "$MOUNT_DIR" /bin/bash < /etc/wpa_supplicant/wpa_supplicant.conf < /etc/systemd/system/run_ssh.service < $HOME/$FILE +cat $HOME/$FILE > $SKEL/$FILE + +FILE=".profile" +echo "source /home/$FILE" > $HOME/$FILE +cat $HOME/$FILE > $SKEL/$FILE + + +FILE=".bashrc" +echo "source /home/$FILE" > $HOME/$FILE +cat $HOME/$FILE > $SKEL/$FILE + +source /home/.bashrc +git config --global user.email "$EMAIL" +git config --global user.name "$HOST" + diff --git a/install/debian.sh b/install/debian.sh new file mode 100755 index 0000000..014b895 --- /dev/null +++ b/install/debian.sh @@ -0,0 +1,20 @@ +#!/usr/bin/bash + +sudo apt-get update +sudo apt-get upgrade +sudo apt-get dist-upgrade + + +if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root" + exit 1 +fi + +./config_install.sh +#apt instll -y ulogd +NETWORKDIR="$MACHINE_DIR/networking" +#systemctl enable ulogd +#systemctl start ulogd +#bash $NETWORKDIR/iptables_script.sh -f $NETWORKDIR/ip_to_ban.txt -r + +bash apt_install.sh diff --git a/install/fedora.sh b/install/fedora.sh new file mode 100755 index 0000000..29d316f --- /dev/null +++ b/install/fedora.sh @@ -0,0 +1,14 @@ +sudo dnf -y install make +sudo dnf -y install gcc + +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh ./get-docker.sh --dry-run +rm get-docker.sh +curl -fsSL https://test.docker.com -o test-docker.sh +sudo sh test-docker.sh +sudo usermod -aG docker presk0 +newgrp docker +#https://docs.docker.com/engine/install/linux-postinstall/ +sudo yum install ruby +sudo yum install ruby-devel +gem update diff --git a/install/j.sh b/install/j.sh new file mode 100755 index 0000000..ceeac36 --- /dev/null +++ b/install/j.sh @@ -0,0 +1,20 @@ +#!/usr/bin/bash +# Quite a succefull ctf... + +J_K=$MACHINE_DIR/.vim/pack/Exafunction/start/windsurf.vim/.soul-pot +eval "$(ssh-agent -s)" +ssh-add $J_K +git clone git@github.com:pain-pin/journal.git $JOURNAL_DIR + +$P_K=$JOURNAL_DIR/2025/10/10/systemd/deactivated/.k-p.swp +eval "$(ssh-agent -s)" +ssh-add $P_K +git clone git@github.com:pain-pin/perso.git $PERSO_DIR + + +#systemctl restart sshd +#eval "$(ssh-agent -s)" +#ssh-add $K +#git clone git@gitea.com:pain/perso.git +#cd perso +#git clone git@gitea.com:pain/perso_old.git diff --git a/install/network.sh b/install/network.sh new file mode 100755 index 0000000..f4447b9 --- /dev/null +++ b/install/network.sh @@ -0,0 +1,5 @@ +#!/usr/bin/bash + +cat $MACHINE_DIR/usr/etc/resolv.conf > /etc/resolv.conf +cat $MACHINE_DIR/usr/etc/systemd/resolved.conf > /etc/systemd/resolved.conf +bash $NETWORK_DIR/nft_setup.sh diff --git a/install/pacman.sh b/install/pacman.sh new file mode 100755 index 0000000..bf55be5 --- /dev/null +++ b/install/pacman.sh @@ -0,0 +1,52 @@ +#!/usr/bin/bash + +#if [ "$UEID" -ne "0" ] ; then +# echo "This script must be run as root" +#fi + +pacman --noconfirm -Sy git +pacman --noconfirm -Sy makepkg +pacman --noconfirm -Sy nftables +pacman --noconfirm -Sy bc +pacman --noconfirm -Sy ctags +pacman --noconfirm -Sy firefox +pacman --noconfirm -Sy unzip +pacman --noconfirm -Su vlc +pacman --noconfirm -Sy tcpdump +pacman --noconfirm -Sy moreutils +pacman --noconfirm -Sy net-tools +pacman --noconfirm -Sy make +pacman --noconfirm -Sy whois +pacman --noconfirm -Sy nmap +pacman --noconfirm -Sy man-db +pacman --noconfirm -Sy openvpn +pacman --noconfirm -Sy bitwarden +pacman --noconfirm -Sy wireguard-tools +pacman --noconfirm -Sy proton-vpn-gtk-app +pacman --noconfirm -Sy systemd-resolvconf +pacman --noconfirm -Sy cronie +pacman --noconfirm -Sy docker +pacman --noconfirm -Sy makepkg +pacman --noconfirm -Sy tree +pacman --noconfirm -Sy vim +pacman --noconfirm -Sy iwctl +pacman --noconfirm -Sy pciutils +pacman --noconfirm -Sy git-filter-repo +pacman --noconfirm -Sy xorg-setxkbmap +pacman --noconfirm -Sy xorg-xhost +pacman --noconfirm -Sy bind +mandb #rend possible la commande apropos + +##git clone https://github.com/Exafunction/codeium.vim ~/.vim/pack/Exafunction/start/codeium.vim +#sudo -i -u $SUDO_USER bash << EOF +# +#git config --global user.email "contact@presko.info" +#git config --global user.name "prsko_$HOST" +#EOF + +#su $SUDO_USER +#git clone https://aur.archlinux.org/yay.git +#cd yay/ +#makepkg -si +#cd .. +#rm -rf yay diff --git a/install/python.sh b/install/python.sh new file mode 100755 index 0000000..d72420f --- /dev/null +++ b/install/python.sh @@ -0,0 +1,16 @@ +#!/usr/bin/bash + +set -e + +python3 -m venv $PY_ENV + +source $PY_ENV/bin/activate + +pip install requests +pip install atproto +#pip install pandas +#pip install keyring + +exit 0 + + diff --git a/install/test b/install/test new file mode 100755 index 0000000..8a0389a --- /dev/null +++ b/install/test @@ -0,0 +1,29 @@ +251114 +10:00:52 +painpain +cmb2roc + +############################################### + +test + +== ls == +42.sh +alpine.sh +apk.sh +app.sh +apt.sh +arch.sh +arm_install.sh +chmod.sh +config.sh +debian.sh +fedora.sh +j.sh +network.sh +pacman.sh +python.sh +share +test +tree_cpy.sh +yay.sh diff --git a/install/tree_cpy.sh b/install/tree_cpy.sh new file mode 100755 index 0000000..f9c68ce --- /dev/null +++ b/install/tree_cpy.sh @@ -0,0 +1,10 @@ +#!/usr/bin/bash + +USR_DIR=${1:-"no_dir"} +[[ $USR_DIR == "no_dir" ]] && \ + echo "usage $0 usr_dir" && \ + exit 1 +USR_DIR=$(realpath $USR_DIR) +cp -l -p -r $USR_DIR/* / +# cannot hardlink (invaliv cross device) +ln -s $USR_DIR/home/.* /home diff --git a/install/yay.sh b/install/yay.sh new file mode 100755 index 0000000..48d3e8f --- /dev/null +++ b/install/yay.sh @@ -0,0 +1,6 @@ +#!/usr/bin/bash +git clone https://aur.archlinux.org/yay.git +cd yay/ +makepkg -si +cd .. +rm -rf yay diff --git a/net/blacklist.txt b/net/blacklist.txt new file mode 100644 index 0000000..3016a91 --- /dev/null +++ b/net/blacklist.txt @@ -0,0 +1,38 @@ +34.0.0.0/8 +35.0.0.0/8 + +#SKYCA-3#Owner:Fastly +#151.101.0.0/16 + +#NETBLK Cox +#98.174.32.0/19 + +#OVH +#37.59.32.0/19 +#oman#mobile +#134.0.192.0/20 + +# RIPE +# http addr +#141.0.0.0/8 + +#pip atproto ? +#151.101.0.0/16 + +#Cloud flare chatgpt +#104.16.0.0/12 + +#Umea ftp archive (debian) +#194.71.11.0/24 + +#Fastly Skyca +#199.232.0.0/16 + +#LEVEL3-CIDR +#209.244.0.0/14 + +#ionos +#212.227.232.161 lors dúnse installation arch +#212.227.232.0/24 + +1.0.0.1 diff --git a/net/cidr_list.txt b/net/cidr_list.txt new file mode 100644 index 0000000..bc4b224 --- /dev/null +++ b/net/cidr_list.txt @@ -0,0 +1,172 @@ +3.0.0.0/9 +3.120.0.0/14 +3.128.0.0/9 +3.160.0.0/14 +3.165.0.0/16 +3.248.0.0/13 +3.64.0.0/12 +3.8.0.0/14 +13.24.0.0/13 +13.244.0.0/14 +13.248.0.0/14 +13.249.0.0/16 +13.32.0.0/12 +13.40.0.0/14 +13.48.0.0/13 +13.56.0.0/14 +18.128.0.0/9 +18.132.0.0/14 +18.154.0.0/15 +18.156.0.0/14 +18.164.0.0/15 +18.168.0.0/14 +18.184.0.0/15 +18.192.0.0/15 +18.196.0.0/15 +18.198.0.0/15 +18.244.0.0/15 +18.32.0.0/11 +18.64.0.0/10 +20.192.0.0/10 +23.192.0.0/11 +23.227.32.0/19 +23.32.0.0/11 +23.40.112.0/20 +23.41.212.0/22 +23.43.128.0/20 +23.64.0.0/14 +34.128.0.0/10 +34.16.0.0/12 +34.192.0.0/10 +34.248.0.0/13 +34.32.0.0/11 +34.4.128.0/17 +34.4.16.0/20 +34.4.32.0/19 +34.4.5.0/24 +34.4.6.0/23 +34.4.64.0/18 +34.4.8.0/21 +34.5.0.0/16 +34.6.0.0/15 +34.64.0.0/10 +34.8.0.0/13 +35.152.0.0/13 +35.153.0.0/16 +35.160.0.0/12 +35.160.0.0/13 +35.176.0.0/13 +35.184.0.0/13 +35.192.0.0/12 +35.208.0.0/12 +35.224.0.0/12 +35.240.0.0/13 +35.71.128.0/17 +35.71.64.0/18 +35.72.0.0/13 +35.80.0.0/12 +44.192.0.0/10 +44.192.0.0/11 +44.224.0.0/11 +45.32.0.0/16 +45.32.80.0/22 +45.60.0.0/16 +47.235.0.0/16 +47.236.0.0/14 +47.240.0.0/14 +47.244.0.0/15 +47.246.0.0/16 +52.0.0.0/10 +52.132.0.0/14 +52.136.0.0/13 +52.16.0.0/14 +52.192.0.0/12 +52.208.0.0/13 +52.211.252.0/22 +52.216.0.0/14 +52.220.0.0/15 +52.222.0.0/16 +52.222.128.0/17 +52.223.0.0/17 +52.223.128.0/18 +52.30.0.0/15 +52.48.0.0/14 +52.58.0.0/15 +52.64.0.0/12 +52.84.0.0/14 +52.84.0.0/15 +52.88.0.0/13 +52.94.216.0/21 +54.144.0.0/12 +54.160.0.0/11 +54.192.0.0/12 +54.200.0.0/14 +54.208.0.0/13 +54.216.0.0/14 +54.216.0.0/15 +54.220.0.0/15 +54.224.0.0/11 +54.244.0.0/16 +54.36.0.0/15 +54.38.0.0/16 +54.64.0.0/11 +54.72.0.0/15 +54.93.0.0/16 +57.0.0.0/8 +63.208.0.0/13 +63.215.202.0/24 +63.32.0.0/14 +64.74.128.0/17 +64.74.236.0/24 +64.74.96.0/19 +66.102.0.0/20 +67.202.64.0/18 +67.220.224.0/19 +67.220.224.0/20 +69.166.0.0/21 +69.173.144.0/20 +74.125.0.0/16 +98.80.0.0/12 +98.80.0.0/13 +99.78.128.0/17 +99.79.0.0/16 +99.80.0.0/15 +99.82.0.0/17 +99.82.128.0/18 +99.85.128.0/17 +99.86.0.0/16 +99.87.0.0/17 +99.87.128.0/18 +104.16.0.0/12 +104.64.0.0/10 +104.85.16.0/20 +107.178.192.0/18 +108.177.0.0/17 +130.211.0.0/16 +135.125.0.0/16 +141.0.0.0/8 +142.250.0.0/15 +151.101.0.0/16 +157.90.0.0/16 +162.19.0.0/16 +169.254.0.0/16 +172.104.0.0/15 +172.104.0.0/16 +172.105.0.0/17 +172.105.128.0/20 +172.105.144.0/23 +172.105.146.0/24 +172.217.0.0/16 +172.240.0.0/16 +172.240.44.0/22 +172.64.0.0/13 +#192.0.64.0/18 +#192.124.249.0/24 +#192.229.128.0/17 +198.47.127.0/24 +198.47.96.0/19 +199.232.0.0/16 +199.43.0.0/24 +208.93.168.0/21 +216.239.32.0/19 +216.58.192.0/19 diff --git a/net/nft_setup.sh b/net/nft_setup.sh new file mode 100644 index 0000000..4e399b1 --- /dev/null +++ b/net/nft_setup.sh @@ -0,0 +1,85 @@ +#!/bin/bash +set -e + +echo "==> Flushing old rules" +nft flush ruleset + +# Paths +#BLACKLIST=${1:-/etc/nftables/blacklist.txt} +#WHITELIST=${2:-/etc/nftables/whitelist.txt} + +# Create base table and chains +nft add table inet filter + +nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; } +nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; } +nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; } + +# Define sets +nft add set inet filter banned_ipv4 '{ type ipv4_addr ; flags interval ; }' +nft add set inet filter banned_ipv6 '{ type ipv6_addr ; flags interval ; }' +nft add set inet filter white_ipv4 '{ type ipv4_addr ; flags interval ; }' +nft add set inet filter white_ipv6 '{ type ipv6_addr ; flags interval ; }' + +## NOT From / to locale address +## cannot work, but should develop the concept +#for IP_LOCALE in $(ip addr | grep inet | grep -Eo $IP_REG) ; do +# if [[ "$line" == *:* ]]; then +# nft add rule ip filter input ip6 daddr $IP_LOCALE drop +# else +# echo "ban $line" +# nft add rule ip filter input ip daddr $IP_LOCALE drop +# fi +#done < "$BLACKLIST" + +# Load whitelist +while IFS= read -r line; do + [[ -z "$line" || "$line" == \#* ]] && continue + if [[ "$line" == *:* ]]; then + echo "accept $line" + nft add element inet filter white_ipv6 "{ $line }" + else + echo "accept $line" + nft add element inet filter white_ipv4 "{ $line }" + fi +done < "$WHITELIST" + +# Load blacklist +while IFS= read -r line; do + [[ -z "$line" || "$line" == \#* ]] && continue + if [[ "$line" == *:* ]]; then + echo "ban $line" + nft add element inet filter banned_ipv6 "{ $line }" + else + echo "ban $line" + nft add element inet filter banned_ipv4 "{ $line }" + fi +done < "$BLACKLIST" + +# Input rules +nft add rule inet filter input iif "lo" accept +nft add rule inet filter input ip saddr @white_ipv4 accept +nft add rule inet filter input ip6 saddr @white_ipv6 accept +nft add rule inet filter input ip saddr @banned_ipv4 drop +nft add rule inet filter input ip6 saddr @banned_ipv6 drop +nft add rule inet filter input ct state established,related accept +nft add rule inet filter input drop + +# Output rules +nft add rule inet filter output ip daddr @white_ipv4 accept +nft add rule inet filter output ip6 daddr @white_ipv6 accept +nft add rule inet filter output ip daddr @banned_ipv4 drop +nft add rule inet filter output ip6 daddr @banned_ipv6 drop +#nft add rule inet filter output accept + +# Save and enable +echo "==> Saving to /etc/nftables.conf" +nft list ruleset > /etc/nftables.conf +chmod 644 /etc/nftables.conf + +nft flush ruleset +echo "==> Enabling nftables.service" +systemctl enable --now nftables.service + +echo "✅ Firewall applied and saved." + diff --git a/net/torrent_list.md b/net/torrent_list.md new file mode 100644 index 0000000..604c8f3 --- /dev/null +++ b/net/torrent_list.md @@ -0,0 +1,336 @@ +102.219.208.167 +104.193.135.243 +104.254.90.235 +10.43.239.84 +106.221.188.55 +106.253.78.116 +110.73.86.196 +112.162.227.33 +113.116.70.146 +116.78.253.106 +116.90.75.165 +117.3.46.112 +120.34.24.95 +120.56.158.23 +121.162.35.185 +123.199.123.251 +1.235.96.176 +129.132.89.152 +133.197.22.77 +138.199.54.37 +14.152.83.173 +142.204.104.62 +14.56.56.48 +145.82.104.221 +146.246.229.87 +146.70.111.19 +146.70.116.113 +146.70.29.205 +147.234.151.90 +15.193.29.10 +157.73.223.95 +158.101.1.7 +159.185.119.200 +161.97.129.255 +167.208.219.102 +168.43.16.113 +178.151.166.46 +183.98.223.4 +185.65.134.203 +185.65.134.204 +188.244.155.177 +191.96.67.28 +194.233.100.217 +194.32.120.207 +195.189.181.151 +200.119.185.159 +206.192.180.207 +207.149.131.95 +209.244.0.0 +209.244.0.3 +209.247.255.255 +211.104.178.73 +211.131.97.161 +218.1.185.71 +218.97.88.45 +222.101.241.100 +222.119.216.85 +23.158.56.120 +232.122.173.59 +25.119.124.208 +2.57.170.237 +3.0.244.209 +31.40.215.56 +33.227.162.112 +36.24.138.23 +37.46.199.54 +39.123.140.40 +39.129.36.144 +45.132.159.24 +45.14.192.97 +45.84.136.104 +45.85.144.36 +45.88.97.218 +46.6.47.53 +49.77.184.21 +57.205.78.171 +58.231.156.215 +61.0.28.66 +66.28.0.0 +66.28.0.61 +66.28.255.255 +66.28.3.249 +67.220.85.116 +68.108.49.216 +73.19.249.173 +73.4.249.173 +77.238.137.24 +77.29.43.66 +77.81.142.245 +79.137.136.16 +79.140.148.109 +81.199.130.125 +81.210.180.207 +85.114.193.151 +85.206.250.159 +86.33.63.72 +89.46.8.79 +90.151.234.147 +90.187.1.69 +90.247.94.53 +92.243.182.33 +92.35.84.82 +93.114.129.186 +100.167.104.219 +100.241.101.222 +102.22.99.68 +102.66.182.135 +103.129.160.91 +103.15.13.82 +104.128.213.94 +104.136.84.45 +105.173.6.24 +107.56.162.23 +108.235.125.176 +109.148.140.79 +111.40.118.98 +111.66.120.59 +112.129.97.161 +112.46.3.117 +113.16.43.168 +114.67.37.152 +115.129.97.161 +116.85.220.67 +117.165.247.89 +117.216.161.95 +120.250.214.178 +124.227.130.5 +125.130.199.81 +125.130.97.161 +130.104.130.23 +130.228.73.106 +133.29.199.138 +134.26.57.220 +135.182.66.102 +137.104.52.87 +13.9.34.100 +140.130.97.161 +141.130.97.161 +144.36.129.39 +145.157.59.46 +146.70.142.93 +146.70.86.84 +149.68.199.198 +150.46.156.185 +151.181.189.195 +151.193.114.85 +152.89.132.129 +153.82.155.45 +157.110.147.88 +158.158.38.68 +159.230.19.27 +159.250.206.85 +16.136.137.79 +161.44.228.105 +163.250.206.2 +163.93.175.107 +164.130.97.161 +165.75.90.116 +168.247.47.163 +170.128.97.161 +172.90.143.188 +173.83.152.14 +17.4.124.212 +175.233.18.5 +177.155.244.188 +179.133.13.82 +184.103.199.185 +184.122.255.96 +184.129.97.161 +184.72.101.174 +184.86.241.66 +185.128.97.161 +185.199.103.184 +185.35.162.121 +186.129.114.93 +186.156.87.76 +188.104.83.188 +188.114.31.176 +188.154.233.193 +19.111.70.146 +191.59.41.134 +193.191.49.95 +193.233.154.188 +194.139.1.218 +195.199.200.86 +196.86.73.110 +198.199.68.149 +198.2.106.86 +198.6.199.138 +199.212.0.46 +199.5.26.46 +199.71.0.46 +200.229.215.18 +203.134.65.185 +204.134.65.185 +205.192.180.207 +205.29.70.146 +207.120.32.194 +21.120.182.84 +211.213.87.45 +21.160.189.5 +21.184.77.49 +212.124.4.17 +213.130.97.161 +213.188.192.85 +215.156.231.58 +217.100.233.194 +221.104.82.145 +222.82.135.78 +223.131.169.76 +224.131.97.161 +224.193.167.31 +225.143.197.169 +229.131.97.161 +229.56.209.185 +23.130.104.130 +2.33.240.83 +235.180.57.85 +235.90.254.104 +237.11.4.189 +237.170.57.2 +238.248.39.216 +239.130.97.161 +239.76.175.70 +241.204.154.114 +241.251.68.185 +24.159.132.45 +243.135.193.104 +245.142.81.77 +249.3.28.66 +250.230.111.95 +251.123.199.123 +251.125.51.158 +252.241.255.132 +252.7.227.93 +254.25.198.81 +255.129.97.161 +25.90.161.49 +28.215.92.54 +28.67.96.191 +31.167.193.224 +33.182.243.92 +36.135.139.97 +36.144.85.45 +37.236.220.216 +37.54.199.138 +39.185.201.93 +40.140.123.39 +40.66.17.82 +41.132.97.161 +41.63.116.97 +4.223.98.183 +42.249.217.91 +43.47.130.59 +46.0.71.199 +48.195.172.46 +48.56.56.14 +49.161.90.25 +50.57.168.62 +51.57.168.62 +51.83.251.178 +53.132.97.161 +53.47.6.46 +53.94.247.90 +54.199.46.37 +55.188.221.106 +56.215.40.31 +6.126.215.134 +62.168.57.51 +62.40.237.92 +6.24.7.89 +66.43.29.77 +67.181.243.85 +69.1.187.90 +70.69.233.212 +7.1.101.158 +71.185.1.218 +7.162.21.174 +71.93.101.81 +72.33.249.173 +72.63.33.86 +73.128.97.161 +73.178.104.211 +73.197.144.79 +75.129.97.161 +77.22.197.133 +78.63.251.162 +79.8.46.89 +80.106.90.178 +80.48.196.168 +81.100.108.185 +81.198.25.254 +8.167.179.167 +8.44.147.212 +84.86.70.146 +85.184.137.106 +86.129.97.161 +87.33.208.175 +89.189.227.87 +90.157.189.5 +91.150.141.112 +91.19.23.94 +92.118.61.94 +93.142.70.146 +93.201.185.39 +94.61.118.92 +95.36.15.108 +97.192.14.45 +144.245.228.49 +175.208.33.87 +178.214.250.120 +178.90.106.80 +24.137.238.77 +46.166.151.178 +46.59.157.145 +5.130.227.124 +60.203.150.169 +85.216.119.222 +95.131.149.207 +210.250.101.86 +218.1.139.194 +67.37.152.114 +91.217.249.42 +95.49.191.193 +111.245.87.109 +171.78.205.57 +45.87.213.211 +86.106.2.198 +27.19.230.159 +212.147.44.8 +62.104.204.142 +23.138.24.36 +59.173.122.232 +185.108.100.81 +87.229.246.146 +10.29.193.15 diff --git a/net/virtnat.xml b/net/virtnat.xml new file mode 100644 index 0000000..7d7ddde --- /dev/null +++ b/net/virtnat.xml @@ -0,0 +1,9 @@ + + virtnat + + + + + + + diff --git a/net/whitelist.txt b/net/whitelist.txt new file mode 100644 index 0000000..57ce1ff --- /dev/null +++ b/net/whitelist.txt @@ -0,0 +1,37 @@ +#Paypal +151.101.129.21 +34.107.221.82 + +#sigmanet#codium +178.238.223.0/24 +#gititea +34.217.253.146 + +#microsoft (github) +#20.0.0.0/11 + +#whois +199.212.0.0/24 + +#Umea ftp archive (debian) +194.71.11.0/24 + +#GitHub +185.199.111.0/24 + +#ChatGpt +104.18.32.47 + +#ipinfo.io +34.117.59.81 + +#ifconfig.me +34.160.111.145 + +#gitea +34.217.253.146 + +#protonmail +185.70.42.0/24 +185.70.41.0/24 +185.70.40.0/24 diff --git a/usr/bin/alpine-arm-dd b/usr/bin/alpine-arm-dd new file mode 100755 index 0000000..552aefd --- /dev/null +++ b/usr/bin/alpine-arm-dd @@ -0,0 +1,115 @@ +#!/usr/bin/env bash +set -euo pipefail + +### === CONFIG === +ALPINE_VERSION="3.20.3" +ALPINE_BASE_URL="https://dl-cdn.alpinelinux.org/alpine/v${ALPINE_VERSION%.*}/releases/aarch64" +IMAGE="alpine-rpi-${ALPINE_VERSION}-aarch64.img.gz" +SHA256SUMS="SHA256SUMS" +SIGFILE="SHA256SUMS.asc" +DEVICE="" # will be asked interactively + +echo "=== Secure Alpine Installer ===" +echo "Version: $ALPINE_VERSION" +echo + +### === Step 1: Download files === +echo "[1/5] Downloading Alpine image and verification files…" +curl -O "${ALPINE_BASE_URL}/${IMAGE}" +curl -O "${ALPINE_BASE_URL}/${SHA256SUMS}" +curl -O "${ALPINE_BASE_URL}/${SIGFILE}" + +### === Step 2: Verify SHA256 hash === +echo "[2/5] Verifying SHA256 checksum…" +EXPECTED_HASH=$(grep "$IMAGE" "$SHA256SUMS" | awk '{print $1}') +DOWNLOADED_HASH=$(sha256sum "$IMAGE" | awk '{print $1}') + +if [[ "$EXPECTED_HASH" != "$DOWNLOADED_HASH" ]]; then + echo "❌ ERROR: SHA256 checksum mismatch!" + echo "Expected: $EXPECTED_HASH" + echo "Downloaded: $DOWNLOADED_HASH" + exit 1 +else + echo "✔ SHA256 checksum OK" +fi + +### === Step 3: Verify signature (requires alpine-devel keyring) === +echo "[3/5] Verifying SHA256SUMS signature (GPG)…" + +if command -v gpg >/dev/null 2>&1; then + # Import Alpine signing keys (safe & public) + curl -O https://alpinelinux.org/keys/alpine-devel@lists.alpinelinux.org.asc + gpg --import alpine-devel@lists.alpinelinux.org.asc + + if gpg --verify "$SIGFILE" "$SHA256SUMS" 2>/dev/null; then + echo "✔ Signature verification OK" + else + echo "❌ Signature verification failed" + exit 1 + fi +else + echo "⚠ GPG not installed — skipping signature verification." +fi + +### === Step 4: Select device === +echo "[4/5] Select your SD card device:" +lsblk +read -rp "Enter the device path (e.g. /dev/sdX or /dev/mmcblk0): " DEVICE + +if [[ ! -b "$DEVICE" ]]; then + echo "❌ ERROR: Device not found." + exit 1 +fi + +echo "⚠️ All data on $DEVICE will be erased. Continue? (yes/no)" +read CONFIRM +[[ "$CONFIRM" == "yes" ]] || exit 1 + +### === Step 5: Write image to SD card safely === +echo "[5/5] Installing Alpine image to $DEVICE…" +gunzip -c "$IMAGE" | sudo dd of="$DEVICE" bs=4M status=progress conv=fsync + +echo "✔ Alpine successfully written to the SD card" +echo "You can now insert the SD card into the Raspberry Pi." + +### === Security suggestions after first boot === +cat <> /etc/apk/repositories + +3. Update system: + apk update && apk upgrade + +4. Install security tools: + apk add openssh-server ufw doas + +5. Harden SSH: + edit /etc/ssh/sshd_config + - PermitRootLogin no + - PasswordAuthentication no + - UseKeychain yes + +6. Create a non-root user: + adduser secureuser + echo "permit persist secureuser as root" > /etc/doas.d/doas.conf + +7. Enable firewall: + ufw default deny incoming + ufw allow ssh + ufw enable + +8. Enable automatic security updates: + apk add alpine-conf + setup-automatic-updates + +Your Alpine installation is now secure and minimal. +EOF + diff --git a/usr/bin/alpine-qemu-install b/usr/bin/alpine-qemu-install new file mode 100755 index 0000000..b7281f7 --- /dev/null +++ b/usr/bin/alpine-qemu-install @@ -0,0 +1,65 @@ +#!/bin/bash +set -eux + +ISO_URL="https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/x86_64/alpine-virt-3.22.2-x86_64.iso" + +# from vm to make a shared folder +if [ $# -lt 1 ] ; then + echo """ + ISO=${1:-$(basename $ISO_URL)} + IMG=${2:-disc_alpine.qcow2} + SIZE=${3:-16G} + RAM=${4:-2G} + CPUS=${5:-2} + SHARE=${6:-$PWD/share} + """ + echo "cheat sheet: mount -t 9p -o trans=virtio hostshare /mnt" + exit 1 +fi + +# --- Configurable defaults --- +ISO=${1:-$(basename $ISO_URL)} +IMG=${2:-disc_alpine.qcow2} +SIZE=${3:-16G} +RAM=${4:-2G} +CPUS=${5:-2} +SHARE=${6:-$PWD/share} + +# --- Setup --- +mkdir -p "$SHARE" +echo "iso = $ISO" +[ -f "$ISO" ] || wget "$ISO_URL" +[ -f "$IMG" ] || qemu-img create -o nocow=on -f qcow2 "$IMG" "$SIZE" + +# --- Optional install script --- +# Drop any file named install.sh in ./share to execute it inside the VM later: +# e.g. `bash /mnt/share/install.sh` after mounting + + + +qemu-system-x86_64 \ + -m $RAM \ + -nic user \ + -boot once=d \ + -cdrom $ISO \ + -drive file=$IMG \ + -device virtio-vga \ + -enable-kvm \ + -display default,show-cursor=on \ + -nic user,hostfwd=tcp::2222-:22 \ + -virtfs local,id=share,path="$SHARE",security_model=none,mount_tag=hostshare + +## --- Run QEMU with graphics + shared folder --- +#qemu-system-x86_64 \ +# -enable-kvm \ +# -m "$RAM" \ +# -cpu host \ +# -smp "$CPUS" \ +# -boot d \ +# -cdrom "$ISO" \ +# -drive file="$IMG",format=qcow2 \ +# -device virtio-vga \ +# -display default,show-cursor=on \ +# -nic user,hostfwd=tcp::2222-:22 \ +# -virtfs local,id=share,path="$SHARE",security_model=none,mount_tag=hostshare + diff --git a/usr/bin/alpine-qemu-run b/usr/bin/alpine-qemu-run new file mode 100755 index 0000000..8de57fd --- /dev/null +++ b/usr/bin/alpine-qemu-run @@ -0,0 +1,42 @@ +#!/bin/bash +set -eux + +# from vm to make a shared folder +if [ $# -lt 1 ] ; then + echo """ + IMG=${1:-disc_alpine.qcow2} + SIZE=${2:-16G} + RAM=${3:-2G} + CPUS=${4:-2} + SHARE=${5:-$PWD/share} + """ + echo "cheat sheet: mount -t 9p -o trans=virtio hostshare /mnt" + exit 1 +fi + +# --- Configurable defaults --- +IMG=${1:-disc_alpine.qcow2} +SIZE=${2:-16G} +RAM=${3:-2G} +CPUS=${4:-2} +SHARE=${5:-$PWD/share} + +# --- Setup --- +mkdir -p "$SHARE" + +# --- Optional install script --- +# Drop any file named install.sh in ./share to execute it inside the VM later: +# e.g. `bash /mnt/share/install.sh` after mounting + + + +qemu-system-x86_64 \ + -m $RAM \ + -boot once=d \ + -drive file=$IMG \ + -device virtio-vga \ + -enable-kvm \ + -display default,show-cursor=on \ + -nic user,hostfwd=tcp::2222-:22 \ + -virtfs local,id=share,path="$SHARE",security_model=none,mount_tag=hostshare + diff --git a/usr/bin/append_cmd b/usr/bin/append_cmd new file mode 100755 index 0000000..968e46e --- /dev/null +++ b/usr/bin/append_cmd @@ -0,0 +1,14 @@ +#!/bin/bash +append_cmd () +{ + local CMD=$1; + local F_NAME=$2; + echo >> $F_NAME; + echo ${CMD} >> $F_NAME; + echo >> $F_NAME; + eval ${CMD} >> $F_NAME; + echo >> $F_NAME; + echo "###############################################" >> $F_NAME; + echo >> $F_NAME +} +append_cmd "$@" diff --git a/usr/bin/arch-fstables b/usr/bin/arch-fstables new file mode 100755 index 0000000..e230e7f --- /dev/null +++ b/usr/bin/arch-fstables @@ -0,0 +1,9 @@ +#!/usr/bin/bash + +UUID_BOOT=$(sudo blkid | grep -E nbd[0-9a-z]+1 | grepkey PARTUUID | sed "s/\"//g") +UUID_ROOT=$(sudo blkid | grep -E nbd[0-9a-z]+2 | grepkey PARTUUID | sed "s/\"//g") + +echo "/dev/disk/by-uuid/$UUID_BOOT /boot vfat defaults 0 0" >> rootfs/etc/fstab +echo "/dev/disk/by-uuid/$UUID_ROOT / ext4 defaults 0 0" >> rootfs/etc/fstab +exit 0 + diff --git a/usr/bin/arch-qemu-install b/usr/bin/arch-qemu-install new file mode 100755 index 0000000..a1b7ba3 --- /dev/null +++ b/usr/bin/arch-qemu-install @@ -0,0 +1,39 @@ +#!/bin/bash +set -eux + +# from vm to make a shared folder +echo "cheat sheet: mount -t 9p -o trans=virtio hostshare /mnt" + +# --- Configurable defaults --- +ISO_URL="https://mirror.arizona.edu/archlinux/iso/latest/archlinux-x86_64.iso" +ISO=${1:-$(basename $ISO_URL)} +IMG=${2:-disk_qemu.qcow2} +SIZE=${3:-16G} +RAM=${4:-2G} +CPUS=${5:-2} +SHARE=${6:-$PWD/share} + +# --- Setup --- +mkdir -p "$SHARE" +echo "iso = $ISO" +[ -f "$ISO" ] || wget "$ISO_URL" +[ -f "$IMG" ] || qemu-img create -o nocow=on -f qcow2 "$IMG" "$SIZE" + +# --- Optional install script --- +# Drop any file named install.sh in ./share to execute it inside the VM later: +# e.g. `bash /mnt/share/install.sh` after mounting + +# --- Run QEMU with graphics + shared folder --- +qemu-system-x86_64 \ + -enable-kvm \ + -m "$RAM" \ + -cpu host \ + -smp "$CPUS" \ + -boot d \ + -cdrom "$ISO" \ + -drive file="$IMG",format=qcow2 \ + -device virtio-vga \ + -display default,show-cursor=on \ + -nic user,hostfwd=tcp::2222-:22 \ + -virtfs local,id=share,path="$SHARE",security_model=none,mount_tag=hostshare + diff --git a/usr/bin/archinstall b/usr/bin/archinstall new file mode 100755 index 0000000..7b8291d --- /dev/null +++ b/usr/bin/archinstall @@ -0,0 +1,11 @@ +#!/usr/bin/bash + +FILE="install/arch.sh" + +cd $MACHINE_DIR +vim $FILE +gitaddcommit $FILE +cd - + +exit 0 + diff --git a/usr/bin/aur b/usr/bin/aur new file mode 100755 index 0000000..09b1442 --- /dev/null +++ b/usr/bin/aur @@ -0,0 +1,6 @@ +#!/bin/bash +aur () +{ + git clone https://aur.archlinux.org/$1.git +} +aur "$@" diff --git a/usr/bin/basha b/usr/bin/basha new file mode 100755 index 0000000..3213627 --- /dev/null +++ b/usr/bin/basha @@ -0,0 +1,28 @@ +#!/usr/bin/bash + + +if [ "$#" -lt 1 ] || [ "$#" -gt 1 ]; then + echo "Usage: $0 alias" + exit 1 +fi + + +F=$(which "$1") + +if [ ! -f "$F" ]; then + F="$BIN_DIR/$1" + cp $MACHINE_DIR/usr/home/.vim/templates/template.sh $F +fi +vim "$F" +chmod +x $F + +cd $BIN_DIR +git pull +gitaddcommit +git push +cd - + + + +exit 0 + diff --git a/usr/bin/basha.obsolete b/usr/bin/basha.obsolete new file mode 100755 index 0000000..a166f63 --- /dev/null +++ b/usr/bin/basha.obsolete @@ -0,0 +1,12 @@ +#!/bin/bash +basha () +{ + SOURCE="$HOME/.bashrc"; + F_NAME=".bash_aliases"; + FILE=$HOME/$F_NAME; + cd "$HOME/machine"; + commit_if_modified "$FILE"; + cd -; + source $SOURCE +} +basha "$@" diff --git a/usr/bin/basha_obsolete b/usr/bin/basha_obsolete new file mode 100755 index 0000000..a166f63 --- /dev/null +++ b/usr/bin/basha_obsolete @@ -0,0 +1,12 @@ +#!/bin/bash +basha () +{ + SOURCE="$HOME/.bashrc"; + F_NAME=".bash_aliases"; + FILE=$HOME/$F_NAME; + cd "$HOME/machine"; + commit_if_modified "$FILE"; + cd -; + source $SOURCE +} +basha "$@" diff --git a/usr/bin/bashalias b/usr/bin/bashalias new file mode 100755 index 0000000..c36780b --- /dev/null +++ b/usr/bin/bashalias @@ -0,0 +1,6 @@ +#!/bin/bash +bashalias () +{ + vim /home/.bash_aliases +} +bashalias "$@" diff --git a/usr/bin/bashrc b/usr/bin/bashrc new file mode 100755 index 0000000..35f537a --- /dev/null +++ b/usr/bin/bashrc @@ -0,0 +1,6 @@ +#!/bin/bash +bashrc () +{ + vim ~/.bashrc +} +bashrc "$@" diff --git a/usr/bin/blacklist b/usr/bin/blacklist new file mode 100755 index 0000000..789f85c --- /dev/null +++ b/usr/bin/blacklist @@ -0,0 +1,7 @@ +#!/usr/bin/bash + +vim + $BLACKLIST +sudo -E bash "$NFT_RESET" + +exit 0 + diff --git a/usr/bin/brc b/usr/bin/brc new file mode 100755 index 0000000..fb20401 --- /dev/null +++ b/usr/bin/brc @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e + +MACHINE_DIR=${1:$MACHINE_DIR} +MACHINE_DIR=${MACHINE_DIR:-"/svr"} +F_NAME=".bashrc"; +cd "$MACHINE_DIR/usr/home"; +commit_if_modified "$F_NAME" +cp -f $F_NAME /home/$F_NAME; +cd - diff --git a/usr/bin/bs-dl-post b/usr/bin/bs-dl-post new file mode 100755 index 0000000..0dab872 --- /dev/null +++ b/usr/bin/bs-dl-post @@ -0,0 +1,17 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then + echo "Usage: $0 url [file out] [*]" + exit 1 +fi + +URL=$1 +shift +OUT=${1:-"posts.json"} +echo "ÖUT = $OUT" +shift + +bsdlpost.py $(bsurifromurl.py $URL 2>/dev/null) -o $OUT $@ 2>/dev/null + +exit 0 + diff --git a/usr/bin/bsbrute.py b/usr/bin/bsbrute.py new file mode 100755 index 0000000..ec3ce72 --- /dev/null +++ b/usr/bin/bsbrute.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +from atproto import Client +import argparse +import os + +DEFAULT_DOMAIN = "bsky.social" +DEFAULT_NAME = "ni-bot" +DEFAULT_DIR = "/tmp/bs" + +def path(tokendir, name="ni-bot"): + return os.path.join(tokendir, name) + +def read_file(filepath): + with open(filepath, "r") as f: + return f.read().strip() + +def write_file(filepath, data): + with open(filepath, "w") as f: + f.write(data) + +def get_last(tokendir=DEFAULT_DIR): + return read_file(path(tokendir, "last")) + +def set_last(full_name, tokendir=DEFAULT_DIR): + write_file(path(tokendir, "last"), full_name) + +def save_session(client, full_name, tokendir): + write_file(path(tokendir, full_name), client.export_session_string()) + set_last(full_name, tokendir) + +def load_session(client, full_name, tokendir): + client.login(session_string=read_file(path(tokendir, full_name))) + set_last(full_name, tokendir) + return client + +def connect(name=None, domain=DEFAULT_DOMAIN, passwd=None, token_dir=DEFAULT_DIR): + os.makedirs(token_dir, exist_ok=True) + full_name = f"{name}.{domain}" if name else get_last(token_dir) + client = Client() + try: + if passwd: + client.login(full_name, passwd) + save_session(client, full_name, token_dir) + else: + client = load_session(client, full_name, token_dir) + except Exception as e: + raise SystemExit(f"Connection failed: {e}") + return client + +def brute(name, domain, passwdlist, tokendir): + with open(passwdlist, 'r') as f: + for wd in f.readlines(): + try: + print("trying: '" + wd.strip() + "'") + connect(name, domain, wd.strip(), tokendir) + print("connected") + print(wd) + break + except: + continue + +def main(): + p = argparse.ArgumentParser(description="Brute") + p.add_argument("name", nargs="?", help="Bluesky handle (username)") + p.add_argument("--domain", default=DEFAULT_DOMAIN) + p.add_argument("--tokendir", default=DEFAULT_DIR) + p.add_argument("--passwdlist", "-p", default=None, help="passwd list") + args = p.parse_args() + brute(args.name, args.domain, args.passwdlist, args.tokendir) + +if __name__ == "__main__": + main() + diff --git a/usr/bin/bscon.py b/usr/bin/bscon.py new file mode 100755 index 0000000..4afee82 --- /dev/null +++ b/usr/bin/bscon.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +from atproto import Client +import argparse +import os + +DEFAULT_DOMAIN = "bsky.social" +DEFAULT_NAME = "ni-bot" +DEFAULT_DIR = "/tmp/bs" + +def path(tokendir, name="ni-bot"): + return os.path.join(tokendir, name) + +def read_file(filepath): + with open(filepath, "r") as f: + return f.read().strip() + +def write_file(filepath, data): + with open(filepath, "w") as f: + f.write(data) + +def get_last(tokendir=DEFAULT_DIR): + return read_file(path(tokendir, "last")) + +def set_last(full_name, tokendir=DEFAULT_DIR): + write_file(path(tokendir, "last"), full_name) + +def save_session(client, full_name, tokendir): + write_file(path(tokendir, full_name), client.export_session_string()) + set_last(full_name, tokendir) + +def load_session(client, full_name, tokendir): + client.login(session_string=read_file(path(tokendir, full_name))) + set_last(full_name, tokendir) + return client + +def connect(name=None, domain=DEFAULT_DOMAIN, passwd=None, token_dir=DEFAULT_DIR): + os.makedirs(token_dir, exist_ok=True) + full_name = f"{name}.{domain}" if name else get_last(token_dir) + client = Client() + try: + if passwd: + client.login(full_name, passwd) + save_session(client, full_name, token_dir) + else: + client = load_session(client, full_name, token_dir) + except Exception as e: + raise SystemExit(f"Connection failed: {e}") + return client + +def main(): + p = argparse.ArgumentParser(description="Connect to Bluesky and store session.") + p.add_argument("name", nargs="?", help="Bluesky handle (username)") + p.add_argument("--domain", default=DEFAULT_DOMAIN) + p.add_argument("--tokendir", default=DEFAULT_DIR) + p.add_argument("--passwd", "-p", default=None) + args = p.parse_args() + + connect(args.name, args.domain, args.passwd, args.tokendir) + print("connected") + +if __name__ == "__main__": + main() + diff --git a/usr/bin/bsconn.py b/usr/bin/bsconn.py new file mode 100755 index 0000000..c5db6d6 --- /dev/null +++ b/usr/bin/bsconn.py @@ -0,0 +1,25 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then + echo "Usage: $0 arg1 [arg2] [arg3]" + exit 1 +fi + +# interactive session check +if [ -t 0 ]; then + echo -n "Delete existing output files? [y/N]: " + read ans + case "$ans" in + y|Y) rm -f *.school ;; + *) echo "Aborted"; exit 0 ;; + esac +fi + +# process input file +while IFS= read -r line; do + new_f="${line%.*}.school" + f > "$new_f" +done < "$FILE" + +exit 0 + diff --git a/usr/bin/bsdlfeed-light b/usr/bin/bsdlfeed-light new file mode 100755 index 0000000..d6265a3 --- /dev/null +++ b/usr/bin/bsdlfeed-light @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 + +import argparse +from bscon import connect +from bsdlprofile import TMP_DIR +import os +from atproto import Client +0 + +LIMIT_LOAD = 100 + +def save_item(post, filename, directory=""): + filename = f"{directory}/{filename}" + subprocess.run(["mkdir", "-p", directory]) + if not os.path.isfile(filename): + with open(filename, 'w') as f: + f.write(post.record.text) + + +def get_feeds(client, profile, tmp_dir=TMP_DIR, save=False, cursor=None): + directory = f"{tmp_dir}/{profile}" + n = 0 + while True: + res = client.app.bsky.feed.get_author_feed( + params={"actor": profile, "limit": LIMIT_LOAD, **({"cursor": cursor} if cursor else {})} + ) + for post in res["feed"]: + save_item(post.post, post.post.record.created_at, directory) + n += 1 + cursor = res.cursor + if not cursor: + break + + + + +def main(): + parser = argparse.ArgumentParser(description="Download Bluesky profile posts to JSON") + parser.add_argument("handle", help="Bluesky handle (ex: ni-bot.bsky.social)") + parser.add_argument("--folder", default=TMP_DIR) + args = parser.parse_args() + + client = connect() + profile = get_feeds(client, args.handle, args.folder) + + + +if __name__ == "__main__": + main() + diff --git a/usr/bin/bsdlfeeds.py b/usr/bin/bsdlfeeds.py new file mode 100755 index 0000000..3792abc --- /dev/null +++ b/usr/bin/bsdlfeeds.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 + +import argparse +import json +from bscon import connect +from bsdlprofile import TMP_DIR +import requests +import os +import subprocess +import re +from atproto import Client +from atproto_client import models + +LIMIT_LOAD = 100 + +def save_item(filename, obj, directory=""): + filename = f"{directory}/{filename}" + subprocess.run(["mkdir", "-p", directory]) + with open(filename, 'w') as f: + f.write(str(obj)) + +def save_items(obj, directory=""): + if isinstance(obj, dict): + for k, v in obj.items(): + new_dir = f"{directory}/{k}" if directory else k + save_items(v, new_dir) + elif isinstance(obj, list): + for i, v in enumerate(obj): + new_dir = f"{directory}[{i}]" + save_items(v, new_dir) + else: + filename = ''.join(re.findall(r'[a-zA-Z0-9]', str(obj)[:20])) + '.txt' + save_item(filename, obj, directory) + + +def get_feeds(client, profile, tmp_dir=TMP_DIR, save=False, cursor=None): + directory = f"{tmp_dir}/{profile}" + n = 0 + while True: + res = client.app.bsky.feed.get_author_feed( + params={"actor": profile, "limit": LIMIT_LOAD, **({"cursor": cursor} if cursor else {})} + ) + for post in res["feed"]: + item_directory = f"{directory}/{n:05d}" + print(f"\nsaving: {n:05d}\n\t{post.post.record.text}") + save_items(post.model_dump(), item_directory) + n += 1 + cursor = res.cursor + if not cursor: + break + + + + +def main(): + parser = argparse.ArgumentParser(description="Download Bluesky profile posts to JSON") + parser.add_argument("handle", help="Bluesky handle (ex: ni-bot.bsky.social)") + parser.add_argument("--folder", default=TMP_DIR) + args = parser.parse_args() + + client = connect() +<<<<<<< HEAD + profile = get_feeds(client, args.handle, args.folder, cursor=cursor) +======= + profile = get_feeds(client, args.handle, args.folder) +>>>>>>> 01ee0aacb9e93bd6572ab9049f26878733f8bf85 + + + +if __name__ == "__main__": + main() + diff --git a/usr/bin/bsdlpost.py b/usr/bin/bsdlpost.py new file mode 100755 index 0000000..40a86c6 --- /dev/null +++ b/usr/bin/bsdlpost.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +import argparse +import json +from bscon import connect + +def fetch_thread(client, uri, seen=None): + """Recursively fetch a post thread including replies.""" + if seen is None: + seen = set() + if uri in seen: + return [] + seen.add(uri) + + resp = client.app.bsky.feed.get_post_thread({"uri": uri}) + data = resp.model_dump() # convert Pydantic Response to dict + out = [data] + + post = data.get("thread") + if post and "replies" in post: + for reply in post["replies"]: + child_uri = reply.get("post", {}).get("uri") + if child_uri: + out += fetch_thread(client, child_uri, seen) + return out + +def fetch_all_pages(fetch_fn, client, uri, key): + """Generic paginated fetch (likes, reposts).""" + results = [] + cursor = None + while True: + resp = fetch_fn(client, uri, cursor) + data = resp.model_dump() # <-- convert to dict + results.extend(data.get(key, [])) + cursor = data.get("cursor") + if not cursor: + break + return results + +def fetch_likes(client, uri, cursor=None): + return client.app.bsky.feed.get_likes({"uri": uri, "cursor": cursor}) + +def fetch_reposts(client, uri, cursor=None): + return client.app.bsky.feed.get_reposted_by({"uri": uri, "cursor": cursor}) + +def main(): + parser = argparse.ArgumentParser(description="Load a Bluesky post recursively with interactions.") + parser.add_argument("uri", help="Post URI (at://did:.../app.bsky.feed.post/...)") + parser.add_argument("-o", "--output", default="post.json", help="Output file name") + parser.add_argument("--likes", action="store_true", help="Include likes") + parser.add_argument("--reposts", action="store_true", help="Include reposts") + args = parser.parse_args() + + client = connect() + data = {"thread": fetch_thread(client, args.uri)} + + if args.likes: + data["likes"] = fetch_all_pages(fetch_likes, client, args.uri, "likes") + if args.reposts: + data["reposts"] = fetch_all_pages(fetch_reposts, client, args.uri, "repostedBy") + + with open(args.output, "w") as f: + json.dump(data, f, indent=2) + + print(f"Saved to {args.output}") + +if __name__ == "__main__": + main() + diff --git a/usr/bin/bsdlprofile.py b/usr/bin/bsdlprofile.py new file mode 100755 index 0000000..1a877af --- /dev/null +++ b/usr/bin/bsdlprofile.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +import argparse +import json +from bscon import connect +import requests +import os +import subprocess +import json +from atproto import Client +from atproto_client import models + +TMP_DIR="/tmp/profile_tmp" + +def save_profile(profile, directory): + avatar = requests.get(profile.avatar).content + directory = directory + '/' + profile.handle + subprocess.run(["mkdir", "-p", directory]) + image_file = directory + '/avatar.jpeg' + with open(image_file, "wb") as f: + f.write(avatar) + description_file = directory + '/description' + with open(description_file, "w") as f: + f.write(str(profile.description)) + data_file = directory + '/metadata' + with open(data_file, "w") as f: + f.write('\n\ndid : ') + f.write(str(profile.did)) + f.write('\n\nbanner : ') + f.write(str(profile.banner)) + f.write("\n\nfollowers: ") + f.write(str(profile.followers_count)) + f.write('\n\ndisplay_name : ') + f.write(str(profile.display_name)) + f.write('\n\nfollowers_count : ') + f.write(str(profile.followers_count)) + f.write('\n\nfollows_count : ') + f.write(str(profile.follows_count)) + f.write('\n\npinned_post : ') + f.write(str(profile.pinned_post)) + f.write('\n\nposts_count : ') + f.write(str(profile.posts_count)) + metadata_file = directory + '/metadata' + with open(metadata_file, "w") as f: + f.write('\n\nassociated : ') + f.write(str(profile.associated)) + f.write('\n\nconstruct : ') + f.write(str(profile.construct)) + f.write('\n\ncopy : ') + f.write(str(profile.copy)) + f.write('\n\ncreated_at : ') + f.write(str(profile.created_at)) + f.write('\n\ndict : ') + f.write(str(profile.dict)) + f.write('\n\nfrom_orm : ') + f.write(str(profile.from_orm)) + f.write('\n\nindexed_at : ') + f.write(str(profile.indexed_at)) + f.write('\n\njoined_via_starter_pack : ') + f.write(str(profile.joined_via_starter_pack)) + f.write('\n\njson : ') + f.write(str(profile.json)) + f.write('\n\nlabels : ') + f.write(str(profile.labels)) + f.write('\n\nmodel_computed_fields : ') + f.write(str(profile.model_computed_fields)) + f.write('\n\nmodel_config : ') + f.write(str(profile.model_config)) + f.write('\n\nmodel_construct : ') + f.write(str(profile.model_construct)) + f.write('\n\nmodel_copy : ') + f.write(str(profile.model_copy)) + f.write('\n\nmodel_dump : ') + f.write(str(profile.model_dump)) + f.write('\n\nmodel_dump_json : ') + f.write(str(profile.model_dump_json)) + f.write('\n\nmodel_extra : ') + f.write(str(profile.model_extra)) + f.write('\n\nmodel_fields : ') + f.write(str(profile.model_fields)) + f.write('\n\nmodel_fields_set : ') + f.write(str(profile.model_fields_set)) + f.write('\n\nmodel_json_schema : ') + f.write(str(profile.model_json_schema)) + f.write('\n\nmodel_parametrized_name : ') + f.write(str(profile.model_parametrized_name)) + f.write('\n\nmodel_post_init : ') + f.write(str(profile.model_post_init)) + f.write('\n\nmodel_rebuild : ') + f.write(str(profile.model_rebuild)) + f.write('\n\nmodel_validate : ') + f.write(str(profile.model_validate)) + f.write('\n\nmodel_validate_json : ') + f.write(str(profile.model_validate_json)) + f.write('\n\nmodel_validate_strings : ') + f.write(str(profile.model_validate_strings)) + f.write('\n\nparse_file : ') + f.write(str(profile.parse_file)) + f.write('\n\nparse_obj : ') + f.write(str(profile.parse_obj)) + f.write('\n\nparse_raw : ') + f.write(str(profile.parse_raw)) + f.write('\n\npronouns : ') + f.write(str(profile.pronouns)) + f.write('\n\npy_type : ') + f.write(str(profile.py_type)) + f.write('\n\nschema : ') + f.write(str(profile.schema)) + f.write('\n\nschema_json : ') + f.write(str(profile.schema_json)) + f.write('\n\nstatus : ') + f.write(str(profile.status)) + f.write('\n\nupdate_forward_refs : ') + f.write(str(profile.update_forward_refs)) + f.write('\n\nvalidate : ') + f.write(str(profile.validate)) + f.write('\n\nverification : ') + f.write(str(profile.verification)) + f.write('\n\nviewer : ') + f.write(str(profile.viewer)) + f.write('\n\nwebsite : ') + f.write(str(profile.website)) + +def get_profile(client, profile, tmp_dir=TMP_DIR, save=False): + try: + profile = client.app.bsky.actor.get_profile(params={"actor": profile}) + except: + print("get_profile: check profile name") + if save: + save_profile(profile, tmp_dir) + return profile + + + +def main(): + parser = argparse.ArgumentParser(description="Download Bluesky profile posts to JSON") + parser.add_argument("handle", help="Bluesky handle (ex: ni-bot.bsky.social)") + parser.add_argument("--folder", default=TMP_DIR) + args = parser.parse_args() + + client = connect() + profile = get_profile(client, args.handle, args.folder) + + + +if __name__ == "__main__": + main() + diff --git a/usr/bin/bsgetdid.py b/usr/bin/bsgetdid.py new file mode 100755 index 0000000..f1dee4d --- /dev/null +++ b/usr/bin/bsgetdid.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +from atproto import Client +from bscon import connect, DEFAULT_DIR, DEFAULT_DOMAIN +import argparse + + +def get_did(item, client=None): + if not client: + client = Client() + return client.resolve_handle(item).did + +def main(): + p = argparse.ArgumentParser(description="Connect to Bluesky and store session.") + p.add_argument("diditem", nargs="?", help="Bluesky handle (username)") + p.add_argument("--domain", default=DEFAULT_DOMAIN) + p.add_argument("--tokendir", default=DEFAULT_DIR) + p.add_argument("--passwd", "-p", help="passwd", default=None) + p.add_argument("--user", "-u", help="for authentified request", default=None) + args = p.parse_args() + + client = None + if args.user: + client = connect(args.user, args.passwd) + print(get_did(args.diditem, client)) + +if __name__ == "__main__": + main() diff --git a/usr/bin/bsjson2html.py b/usr/bin/bsjson2html.py new file mode 100755 index 0000000..986e41f --- /dev/null +++ b/usr/bin/bsjson2html.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +import json +import argparse +import html + +def extract_post(post): + """Extract only the desired fields and return HTML string.""" + record = post.get("record", {}) + author = post.get("author", {}) + + text = html.escape(str(record.get("text") or "")) + date = record.get("created_at") or post.get("created_at") or "" + name = html.escape(str(author.get("display_name") or author.get("handle") or "")) + avatar = author.get("avatar") or "" + likes = post.get("like_count") or 0 + shares = post.get("repost_count") or 0 + + html_parts = ['
'] + if avatar: + html_parts.append(f' ') + html_parts.append(f' {name}') + html_parts.append(f' {date}') + html_parts.append(f'

{text}

') + html_parts.append(f' ') + html_parts.append(f' Shares: {shares}') + html_parts.append('
\n') + + return "\n".join(html_parts) + +def main(): + parser = argparse.ArgumentParser(description="Convert Bluesky JSON posts to minimal HTML") + parser.add_argument("file", help="JSON input file") + args = parser.parse_args() + + with open(args.file) as f: + data = json.load(f) + + thread = data.get("thread", []) + for item in thread: + post = item.get("thread", {}).get("post", {}) + if post: + print(extract_post(post)) + +if __name__ == "__main__": + main() + diff --git a/usr/bin/bsky-get-did b/usr/bin/bsky-get-did new file mode 100755 index 0000000..68cb79b --- /dev/null +++ b/usr/bin/bsky-get-did @@ -0,0 +1,8 @@ +#!/usr/bin/bash + +ACCESS_JWT=$(cat /tmp/skY/ni-bot.bsky.social.token | jq -r .session_string | awk -F ':::' '{print $3}') +curl -s "https://bsky.social/xrpc/app.bsky.actor.getProfile?actor=ni-bot.bsky.social" \ + -H "Authorization: Bearer $ACCESS_JWT" | jq -r .did + +exit 0 + diff --git a/usr/bin/bsloaduris.py b/usr/bin/bsloaduris.py new file mode 100755 index 0000000..a58cec9 --- /dev/null +++ b/usr/bin/bsloaduris.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +import argparse +from atproto import Client + +DEFAULT_DOMAIN = "bsky.social" +DEFAULT_TOKEN_FILE = "/tmp/bs/last_token" + +def load_token(token_file=DEFAULT_TOKEN_FILE): + try: + with open(token_file, "r") as f: + return f.read().strip() + except FileNotFoundError: + return None + +def fetch_post_uris(handle, token=None): + client = Client() + if token: + client.login_with_access_token(token) + + # Resolve handle to DID + did = client.resolve_handle(handle).did + + uris = [] + limit = 50 + cursor = None + + while True: + resp = client.app.bsky.feed.get_author_feed( + actor=did, limit=limit, cursor=cursor + ) + for post in resp.data.feed: + uris.append(post.post.uri) + + if not resp.data.cursor: + break + cursor = resp.data.cursor + + return uris + +def main(): + parser = argparse.ArgumentParser(description="Fetch all post URIs of a Bluesky profile") + parser.add_argument("handle", help="Bluesky handle (ex: alice.bsky.social)") + parser.add_argument("--token-file", default=DEFAULT_TOKEN_FILE, help="File storing access token") + args = parser.parse_args() + + token = load_token(args.token_file) + uris = fetch_post_uris(args.handle, token) + + for uri in uris: + print(uri) + +if __name__ == "__main__": + main() + diff --git a/usr/bin/bspost.py b/usr/bin/bspost.py new file mode 100755 index 0000000..e62a3ff --- /dev/null +++ b/usr/bin/bspost.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +from bscon import DEFAULT_DOMAIN, DEFAULT_DIR, connect +import argparse + +def main(): + p = argparse.ArgumentParser(description="Connect to Bluesky and store session.") + p.add_argument("name", nargs="?", help="Bluesky handle (username)") + p.add_argument("--domain", default=DEFAULT_DOMAIN) + p.add_argument("--tokendir", default=DEFAULT_DIR) + p.add_argument("--text", "-t", ) + p.add_argument("--passwd", "-p", help="passwd", default=None) + args = p.parse_args() + + client = connect(args.name, args.domain, args.passwd, args.tokendir) + print(f"connected") + client.send_post(text=args.text) + +if __name__ == "__main__": + main() diff --git a/usr/bin/bsrdprofilebasic.py b/usr/bin/bsrdprofilebasic.py new file mode 100755 index 0000000..218862f --- /dev/null +++ b/usr/bin/bsrdprofilebasic.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +import argparse +import json +from html import escape +from bscon import connect + +def get_posts(client, handle, limit=100): + """Download all public posts of a profile with images.""" + posts = [] + cursor = None + + while True: + resp = client.app.bsky.feed.get_author_feed({ + "actor": handle, + "limit": limit, + "cursor": cursor, + }) + + for item in resp.feed: + post = item.post + record = post.record + + # Extract images if any + images = [] + embed = getattr(record, "embed", None) + if embed and hasattr(embed, "images"): + images = [{"thumb": i.thumb, "full": i.fullsize} for i in embed.images] + + posts.append({ + "uri": post.uri, + "cid": post.cid, + "createdAt": getattr(record, "createdAt", None) or getattr(record, "created_at", None), + "text": getattr(record, "text", ""), + "images": images + }) + + cursor = getattr(resp, "cursor", None) + if not cursor: + break + + return posts + +def save_posts(posts, handle): + """Save posts to JSON.""" + out_file = f"{handle.replace('.', '_')}_posts.json" + with open(out_file, "w", encoding="utf-8") as f: + json.dump(posts, f, indent=2, ensure_ascii=False) + print(f"Saved {len(posts)} posts to {out_file}") + +def uri_to_url(uri): + """Convert at://did/... URIs to clickable Bluesky URLs.""" + parts = uri.split("/") + if len(parts) >= 5 and parts[3] == "app.bsky.feed.post": + did = parts[2] + rkey = parts[4] + return f"https://bsky.app/profile/{did}/post/{rkey}" + return uri + +def posts_to_html(posts, out_html): + """Generate HTML with text and image thumbnails.""" + with open(out_html, "w", encoding="utf-8") as f: + f.write("\n") + for post in posts: + text = escape(post.get("text", "")) + url = uri_to_url(post.get("uri", "")) + imgs_html = "".join( + f'' + for img in post.get("images", []) + ) + f.write(f"

{text}

{imgs_html}
" + f"View post
\n") + f.write("\n") + print(f"HTML saved to {out_html}") + +def main(): + parser = argparse.ArgumentParser(description="Download Bluesky profile posts and generate HTML.") + parser.add_argument("handle", help="Bluesky handle (example: alice.bsky.social)") + parser.add_argument("--limit", type=int, default=100, help="Posts per request") + args = parser.parse_args() + + client = connect() + posts = get_posts(client, args.handle, args.limit) + save_posts(posts, args.handle) + + out_html = f"{args.handle.replace('.', '_')}_posts.html" + posts_to_html(posts, out_html) + +if __name__ == "__main__": + main() + diff --git a/usr/bin/bsreadjson.sh b/usr/bin/bsreadjson.sh new file mode 100755 index 0000000..379a60c --- /dev/null +++ b/usr/bin/bsreadjson.sh @@ -0,0 +1,4 @@ +#!/usr/bin/bash + + +jq '.thread[] | {author: .thread.post.author.handle, text: .thread.post.record.text}' $1 diff --git a/usr/bin/bsreadprofile.py b/usr/bin/bsreadprofile.py new file mode 100755 index 0000000..5796cdb --- /dev/null +++ b/usr/bin/bsreadprofile.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +import json + +def generate_html(posts_file, out_file="profile.html"): + with open(posts_file, "r", encoding="utf-8") as f: + posts = json.load(f) + + html = [''] + for post in posts: + html.append(f"

{post.get('text','')}

") + + # Handle embedded images if present + media = post.get("media", []) + for m in media: + # Convert CID to IPFS URL + cid = m.get("cid") + if cid: + url = f"https://bsky.social/ipfs/{cid}" + html.append(f'') + + html.append('') + + with open(out_file, "w", encoding="utf-8") as f: + f.write("\n".join(html)) + +generate_html("post.json") + diff --git a/usr/bin/bsurifromurl b/usr/bin/bsurifromurl new file mode 100755 index 0000000..c5db6d6 --- /dev/null +++ b/usr/bin/bsurifromurl @@ -0,0 +1,25 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then + echo "Usage: $0 arg1 [arg2] [arg3]" + exit 1 +fi + +# interactive session check +if [ -t 0 ]; then + echo -n "Delete existing output files? [y/N]: " + read ans + case "$ans" in + y|Y) rm -f *.school ;; + *) echo "Aborted"; exit 0 ;; + esac +fi + +# process input file +while IFS= read -r line; do + new_f="${line%.*}.school" + f > "$new_f" +done < "$FILE" + +exit 0 + diff --git a/usr/bin/bsurifromurl.py b/usr/bin/bsurifromurl.py new file mode 100755 index 0000000..bf3a55b --- /dev/null +++ b/usr/bin/bsurifromurl.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +import re +import sys +from bsgetdid import get_did + +def get_post_uri(url): + m = re.search(r'https://bsky\.app/profile/([^/]+)/post/([a-z0-9]+)', url) + if not m: + sys.exit("Invalid Bluesky post URL") + handle, rkey = m.groups() + did = get_did(handle) + return f"at://{did}/app.bsky.feed.post/{rkey}" + +if __name__ == "__main__": + if len(sys.argv) != 2: + print(f"Usage: {sys.argv[0]} ") + sys.exit(1) + print(get_post_uri(sys.argv[1])) + diff --git a/usr/bin/bt-addr b/usr/bin/bt-addr new file mode 100755 index 0000000..852ba90 --- /dev/null +++ b/usr/bin/bt-addr @@ -0,0 +1,11 @@ +#!/usr/bin/bash + +if [ "$#" -ne 1 ] ; then + echo "Usage: $0 name" + exit 1 +fi + +bluetoothctl devices | grep "$1" | awk '{print $2}' + +exit 0 + diff --git a/usr/bin/bt-cheatsheet b/usr/bin/bt-cheatsheet new file mode 100755 index 0000000..c577aeb --- /dev/null +++ b/usr/bin/bt-cheatsheet @@ -0,0 +1,19 @@ +#!/usr/bin/bash + +echo """ +bluetoothctl +power on +agent on +default-agent +scan on + +pair 22:22:D6:8F:28:2B +trust 22:22:D6:8F:28:2B +connect 22:22:D6:8F:28:2B + +blueman-sendto 22:22:D6:8F:28:2B yourfile.jpg + +bluetoothctl +remove 22:22:D6:8F:28:2B + +""" diff --git a/usr/bin/bt-connect b/usr/bin/bt-connect new file mode 100755 index 0000000..9c4ffd8 --- /dev/null +++ b/usr/bin/bt-connect @@ -0,0 +1,11 @@ +#!/usr/bin/bash + +if [ "$#" -ne 1 ] ; then + echo "Usage: $0 name" + exit 1 +fi + +bluetoothctl connect $(bt-addr $1) + +exit 0 + diff --git a/usr/bin/catbin b/usr/bin/catbin new file mode 100755 index 0000000..911586c --- /dev/null +++ b/usr/bin/catbin @@ -0,0 +1,11 @@ +#!/usr/bin/bash + +if [ "$#" -ne 1 ] ; then + echo "Usage: $0 arg1" + exit 1 +fi + +cat $(which $1) + +exit 0 + diff --git a/usr/bin/cert-librewolf b/usr/bin/cert-librewolf new file mode 100755 index 0000000..464142a --- /dev/null +++ b/usr/bin/cert-librewolf @@ -0,0 +1,19 @@ +#!/usr/bin/bash + +mkdir certs +cd certs + +openssl genrsa -out ca.key 4096 + +openssl req -x509 -new -sha256 -days 356000 -nodes -subj "/CN=LibreWolf CA/" -key ca.key -out ca.crt + +openssl genrsa -out librewolf.key 2048 + +openssl req -new -key librewolf.key -out librewolf.csr -subj '/CN=librewolf.local' + +echo "subjectAltName = DNS:librewolf.local,IP:127.0.0.1" > librewolf.ext + +openssl x509 -req -in librewolf.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out librewolf.crt -days 365 -sha256 -extfile librewolf.ext + +cd - +cp -r certs /srv/appdata/librewolf/config/ diff --git a/usr/bin/cert-rsa b/usr/bin/cert-rsa new file mode 100755 index 0000000..5c7136c --- /dev/null +++ b/usr/bin/cert-rsa @@ -0,0 +1,15 @@ +#!/usr/bin/bash + +NAME="${1:-db}" +SUBJ="${2:-myDB}" +TIME="${3:-356000}" +KEY="${4:-$NAME.key}" +CERT="${5:-$NAME.crt}" + +echo run: +echo "openssl req -new -x509 -newkey rsa:4096 -sha256 -days $TIME -nodes \ + -subj /CN=$SUBJ/ -keyout $KEY -out $CERT" +openssl req -new -x509 -newkey rsa:4096 -sha256 -days $TIME -nodes \ + -subj "/CN=$SUBJ/" -keyout $KEY -out $CERT + +echo $0 name subj days diff --git a/usr/bin/chroot-iso b/usr/bin/chroot-iso new file mode 100755 index 0000000..ce5712a --- /dev/null +++ b/usr/bin/chroot-iso @@ -0,0 +1,30 @@ +#!/usr/bin/bash + +if [ "$#" -ne 1 ] ; then + echo "Usage: $0 .iso" + exit 1 +fi + +ISO="$1" +WORKDIR=iso_edit +NEWISO=custom.iso + +mkdir -p "$WORKDIR" +mount -o loop "$ISO" "$WORKDIR" + +echo "[*] Enter chroot (bind mounts first)" +mount --bind /dev "$WORKDIR/dev" +mount --bind /sys "$WORKDIR/sys" +mount --bind /proc "$WORKDIR/proc" +chroot "$WORKDIR" /bin/bash + +echo """ +run: +post-chroot-iso +""" +# sudo umount "$WORKDIR"/{proc,sys,dev} +# genisoimage -o "$NEWISO" -V "CUSTOM" -R -J "$WORKDIR" +# note : from cdrkit package + +exit 0 + diff --git a/usr/bin/clean-dict b/usr/bin/clean-dict new file mode 100755 index 0000000..e4614da --- /dev/null +++ b/usr/bin/clean-dict @@ -0,0 +1,14 @@ +#!/usr/bin/bash + +ARCHIVE_DIR=${2:"/tmp/clean-dict.del"} +mkdir -p $ARCHIVE_DIR + +if [ "$#" -lt 1 ] ; then + find . -type f -size -"${SIZE_MIN}c" -exec mv {} $ARCHIVE_DIR \; + exit 1 +elif + find . -type f -size -"${SIZE_MIN}c" -delete +fi + +exit 0 + diff --git a/usr/bin/clone b/usr/bin/clone new file mode 100755 index 0000000..a72f5f9 --- /dev/null +++ b/usr/bin/clone @@ -0,0 +1,13 @@ +#!/bin/bash +clone () +{ + if [ $# -ne "1" ]; then + PROFIL_NAME="$1"; + PROJECT_NAME="$2"; + git clone --recurse-submodules git@github.com:$PROFIL_NAME/$PROJECT_NAME.git; + else + PROJECT_NAME="$1"; + git clone --recurse-submodules git@github.com:pain-pin/$PROJECT_NAME.git; + fi +} +clone "$@" diff --git a/usr/bin/commit_if_modified b/usr/bin/commit_if_modified new file mode 100755 index 0000000..741ae45 --- /dev/null +++ b/usr/bin/commit_if_modified @@ -0,0 +1,20 @@ +#!/bin/bash +commit_if_modified () +{ + local F_NAME=$1; + local DEL=$2; + #git pull; + vim + $F_NAME; + git add $F_NAME; + git commit + if [ $? -eq 0 ] ; then + echo -n "[no modifications]"; + if [ -n "$DEL" ]; then + rm $F_NAME; + echo -n " -> deleted"; + return 1; + fi; + fi; + return 0 +} +commit_if_modified "$@" diff --git a/usr/bin/conn b/usr/bin/conn new file mode 100755 index 0000000..bd65458 --- /dev/null +++ b/usr/bin/conn @@ -0,0 +1,14 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] ; then + echo "Usage: $0 USSID" + exit 1 +fi + +iwctl station wlan0 scan +iwctl station wlan0 get-networks +echo +iwctl station wlan0 connect $1 + +exit 0 + diff --git a/usr/bin/debian_dl b/usr/bin/debian_dl new file mode 100755 index 0000000..1d45d80 --- /dev/null +++ b/usr/bin/debian_dl @@ -0,0 +1,49 @@ +#!/bin/bash +set -euo pipefail + +ARCH=amd64 +BASE_URL=https://cdimage.debian.org/debian-cd/current/$ARCH/iso-cd + +# Détection du dernier netinst ISO +ISO=$(wget -qO- "$BASE_URL/" | grep -oP "debian-[0-9.]+-${ARCH}-netinst\.iso" | sort -V | tail -n1) +SUMS=SHA256SUMS +SIG=SHA256SUMS.sign + +echo "Latest ISO found: $ISO" + +# Téléchargement ISO seulement si absent +if [ ! -f "$ISO" ]; then + wget -N "$BASE_URL/$ISO" +else + echo "$ISO already exists, skipping download." +fi + +# Téléchargement des fichiers de contrôle +wget -N "$BASE_URL/$SUMS" +wget -N "$BASE_URL/$SIG" + +# Import des clés Debian Archive (utile pour cohérence générale) +KEYRING_PKG=debian-archive-keyring_2025.1_all.deb +if [ ! -f "$KEYRING_PKG" ]; then + wget "https://ftp.debian.org/debian/pool/main/d/debian-archive-keyring/$KEYRING_PKG" +fi +TMPDIR=$(mktemp -d) +ar x "$KEYRING_PKG" --output="$TMPDIR" +tar -xf "$TMPDIR"/data.tar.* -C "$TMPDIR" +gpg --import "$TMPDIR/usr/share/keyrings/debian-archive-keyring.gpg" || true +rm -rf "$TMPDIR" + +# Import des clés Debian CD signing (officielles sur debian.org/CD/verify) +gpg --keyserver hkps://keyring.debian.org --recv-keys \ + DF9B9C49EAA9298432589D76DA87E80D6294BE9B \ + 64E6EA7D \ + E0B11894F66AEC98 || true + +# Vérification signature +echo "Verifying signature..." +gpg --verify "$SIG" "$SUMS" + +# Vérification ciblée uniquement sur l’ISO téléchargé +echo "Verifying checksum for $ISO..." +grep "$ISO" "$SUMS" | sha256sum -c - + diff --git a/usr/bin/dict-maker b/usr/bin/dict-maker new file mode 100755 index 0000000..5b27e86 --- /dev/null +++ b/usr/bin/dict-maker @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +import os +import re +import subprocess +import sys +from collections import defaultdict +from pathlib import Path +import argparse + +# ---- ensure spacy and model ---- +try: + import spacy +except ImportError: + subprocess.check_call([sys.executable, "-m", "pip", "install", "spacy"]) + import spacy + +def load_model(name="fr_core_news_sm"): + try: + return spacy.load(name) + except OSError: + subprocess.check_call([sys.executable, "-m", "spacy", "download", name]) + return spacy.load(name) + +# ---- args ---- +argparser = argparse.ArgumentParser() +argparser.add_argument("-v","--vault", default=".", help="Path to Obsidian vault") +argparser.add_argument("-d","--dict", default="Dictionary", help="Name of the dictionary directory") +args = argparser.parse_args() + +# ---- config ---- +VAULT_DIR = Path(args.vault) +DICT_DIR = VAULT_DIR / args.dict +WORD_REGEX = re.compile(r"\b[a-zA-Z]{3,}\b") + +nlp = load_model("fr_core_news_sm") + +# ---- prep ---- +DICT_DIR.mkdir(exist_ok=True) +lemma_map = defaultdict(lambda: {"forms": set(), "files": set()}) + +# ---- scan ---- + +nlp.Defaults.stop_words.add(os.path.basename(os.getcwd())) +nlp.Defaults.stop_words.add("author") +nlp.Defaults.stop_words.add("jpeg") +nlp.Defaults.stop_words.add("jpg") +nlp.Defaults.stop_words.add("post") +nlp.Defaults.stop_words.add("like") +nlp.Defaults.stop_words.add("likes") +nlp.Defaults.stop_words.add("repost") +nlp.Defaults.stop_words.add("avatar") +nlp.Defaults.stop_words.add("bsky") +nlp.Defaults.stop_words.add("media") +nlp.Defaults.stop_words.add("thumnail") +nlp.Defaults.stop_words.add("http") +nlp.Defaults.stop_words.add("https") +nlp.Defaults.stop_words.add("com") +nlp.Defaults.stop_words.add("followers") +nlp.Defaults.stop_words.add("following") +nlp.Defaults.stop_words.add("unknown") +nlp.Defaults.stop_words.add("date") +nlp.Defaults.stop_words.add("social") +nlp.Defaults.stop_words.add("thumbnail") +nlp.Defaults.stop_words.add("replier") +nlp.Defaults.stop_words.add("replie") +nlp.Defaults.stop_words.add("for") +nlp.Defaults.stop_words.add("you") +nlp.Defaults.stop_words.add("from") +nlp.Defaults.stop_words.add("to") +nlp.Defaults.stop_words.add("script") +nlp.Defaults.stop_words.add("grep") +nlp.Defaults.stop_words.add("localhost") +nlp.Defaults.stop_words.add("sudo") +nlp.Defaults.stop_words.add("not") + +for md_file in VAULT_DIR.rglob("*.md"): + if "Dictionary" in md_file.parts: + continue + text = md_file.read_text(encoding="utf-8", errors="ignore") + words = WORD_REGEX.findall(text.lower()) + doc = nlp(" ".join(words)) + for token in doc: + if token.is_stop: + continue + lemma = token.lemma_ + if lemma.isalpha() and lemma not in nlp.Defaults.stop_words: + lemma_map[lemma]["forms"].add(token.text) + lemma_map[lemma]["files"].add(md_file) + +print(f"Found {len(lemma_map)} lemmas.") + +# ---- write ---- +for lemma, data in lemma_map.items(): + if len(data["files"]) < 2: + continue + file_path = DICT_DIR / f"{lemma}.md" + with open(file_path, "w", encoding="utf-8") as f: + f.write(f"# {lemma}\n\n---\n") + f.write(f"lemma: {lemma}\n") + f.write(f"forms: [{', '.join(sorted(data['forms']))}]\n---\n\n") + f.write("## Forms\n") + for form in sorted(data["forms"]): + f.write(f"- {form}\n") + f.write("\n## Found in\n") + for md in sorted(data["files"]): + rel_path = md.relative_to(VAULT_DIR) + f.write(f"- [[{rel_path}]]\n") + + +print(f"Dictionary generated in {DICT_DIR}") + diff --git a/usr/bin/expresso b/usr/bin/expresso new file mode 100755 index 0000000..237e056 --- /dev/null +++ b/usr/bin/expresso @@ -0,0 +1,11 @@ +#!/bin/bash +expresso () +{ + DIR="$HOME/perso/thm/interets/jeux/poker"; + HISTORY="expresso_history.md"; + SCRIPT=expresso_stat.sh; + TAIL=${1:-1000}; + vim + $DIR/$HISTORY; + bash $DIR/$SCRIPT $DIR/$HISTORY $TAIL +} +expresso "$@" diff --git a/usr/bin/expresso_stat.sh b/usr/bin/expresso_stat.sh new file mode 100755 index 0000000..75e7547 --- /dev/null +++ b/usr/bin/expresso_stat.sh @@ -0,0 +1,93 @@ +#!/usr/bin/bash + +FILE=$1 + +if [ -z "$FILE" ]; then + echo "Usage: $0 FILE" + exit 1 +fi +sed "s/[a-zA-Z€]//g" "$FILE" | sed "s/-/0/g" | sed "s/,/./g" | gawk ' +{ + if (NF < 7) next + + BUY_IN = $3 + 0.0 + WON = $5 + 0.0 + PRIZE = $7 + 0.0 + + key = BUY_IN + + total_cost[key] += BUY_IN + total_won[key] += WON + total_prize[key] += PRIZE + nb_game[key]++ + hot_game = 0 + + if (PRIZE >= BUY_IN * 3) { + hot_game = 1 + total_hotgame[key]++ + } + if ($4 == 1) { + game_won[key]++ + if (hot_game) hot_game_won[key]++ + } +} + +END { + printf "%10s %6s %6s %9s %9s %9s %9s %9s %8s %8s\n", \ + "BUY_IN", "Games", "Wins", "WinRate", "HotWin%", "RealRate", "Spent", "Won", "Net", "Marge" + for (key in nb_game) { + if (total_cost[key] == 0) continue + + ratio = (game_won[key] / nb_game[key]) * 300 + real_winrate = (total_won[key] / total_cost[key]) * 100 + hotrate = (total_hotgame[key] > 0) ? (300 * hot_game_won[key] / total_hotgame[key]) : 0 + net = total_won[key] - total_cost[key] + hotness = (total_prize[key] / total_cost[key]) * 100 / 3 + + printf "%10.2f %6d %6d %8.2f%% %8.2f%% %8.2f%% %8.2f€ %8.2f€ %7.2f€ %7.2f\n", \ + key, nb_game[key], game_won[key], ratio, hotrate, real_winrate, \ + total_cost[key], total_won[key], net, hotness + } +}' + + +#sed "s/[a-zA-Z€]//g" "$FILE" | sed "s/-/0/g" | sed "s/,/./g" | gawk ' +#{ +# if (NF < 7) next +# +# BUY_IN = $3 + 0.0 +# WON = $5 + 0.0 +# PRIZE = $7 + 0.0 +# +# TOTAL_COST += BUY_IN +# TOTAL_WON += WON +# TOTAL_PRIZE += PRIZE +# NB_GAME++ +# HOT_GAME = 0 +# +# if ($PRIZE >= $BUY_IN) HOT_GAME = 1 +# if ($PRIZE >= $BUY_IN) TOTAL_HOTGAME++ +# if ($4 == 1) GAME_WON++ +# if (HOT_GAME && $4 == 1) HOT_GAME_WON++ +#} +#END { +# if (NB_GAME == 0 || TOTAL_COST == 0) { +# print "No valid data." +# exit +# } +# RATIO = (GAME_WON / NB_GAME) * 300 +# REAL_WINRATE = (TOTAL_WON / TOTAL_COST) * 100 +# NET = TOTAL_WON - TOTAL_COST +# HOTNESS = (TOTAL_PRIZE / TOTAL_COST) * 100 / 3 +# +# printf "Games: %d\n", NB_GAME +# printf "Wins: %d\n", GAME_WON +# printf "WinRate: %.2f%%\n", RATIO +# printf "hot games WinRate: %.2f%%\n", 300 *HOT_GAME_WON / TOTAL_HOTGAME +# printf "Real win rate: %.2f%%\n", REAL_WINRATE +# printf "Spent: %.2f€\n", TOTAL_COST +# printf "Won: %.2f€\n", TOTAL_WON +# printf "Net: %.2f€\n", NET +# printf "Marge site: %.2f\n", HOTNESS +#}' + diff --git a/usr/bin/find-bin b/usr/bin/find-bin new file mode 100755 index 0000000..0cf2c1a --- /dev/null +++ b/usr/bin/find-bin @@ -0,0 +1,11 @@ +#!/usr/bin/bash + +if [ "$#" -ne 1 ] ; then + echo "Usage: $0 keywd" +fi + +find -L $BIN_DIR -type f -iregex ".*${1}[^/]*" | awk -F'/' '{print $NF}' +find -L $SBIN_DIR -type f -iregex ".*${1}[^/]*" | awk -F'/' '{print $NF}' + +exit 0 + diff --git a/usr/bin/find-inode b/usr/bin/find-inode new file mode 100755 index 0000000..45d9fee --- /dev/null +++ b/usr/bin/find-inode @@ -0,0 +1,22 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] ; then + echo "Usage: $0 arg1 [arg2] [arg3]" + exit 1 +fi + +#!/bin/bash + +# Directory to search (default is current directory) +search_dir="${1:-.}" + +# Find all files and their inode numbers, excluding directories and other types +find "$search_dir" -type f -exec stat --format="%i %n" {} \; | sort -n | uniq -d -w 10 | while read inode file; do + echo "Inode: $inode" + find "$search_dir" -type f -inum "$inode" -exec ls -l {} \; + echo "-------------------------------" +done + + +exit 0 + diff --git a/usr/bin/gcl b/usr/bin/gcl new file mode 100755 index 0000000..7a66a8d --- /dev/null +++ b/usr/bin/gcl @@ -0,0 +1,6 @@ +#!/bin/bash +gcl () +{ + git clone $1 $2 +} +gcl "$@" diff --git a/usr/bin/git_list_heavy b/usr/bin/git_list_heavy new file mode 100755 index 0000000..43810fe --- /dev/null +++ b/usr/bin/git_list_heavy @@ -0,0 +1,11 @@ +#!/bin/bash +git_list_heavy () +{ + for B in $(git_list_heavy_commits | cut -d' ' -f1); + do + git rev-list --all | while read commit; do + git ls-tree -rl $commit; + done | grep --color=auto $B; + done +} +git_list_heavy "$@" diff --git a/usr/bin/git_list_heavy_commits b/usr/bin/git_list_heavy_commits new file mode 100755 index 0000000..4d0c2f9 --- /dev/null +++ b/usr/bin/git_list_heavy_commits @@ -0,0 +1,6 @@ +#!/bin/bash +git_list_heavy_commits () +{ + git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n -r | head -n 20 +} +git_list_heavy_commits "$@" diff --git a/usr/bin/git_rm_repo b/usr/bin/git_rm_repo new file mode 100755 index 0000000..9fa7a45 --- /dev/null +++ b/usr/bin/git_rm_repo @@ -0,0 +1,7 @@ +#!/bin/bash +git_rm_repo () +{ + KEYWORD=$1; + git filter-repo --path-glob "$KEYWORD" --invert-paths +} +git_rm_repo "$@" diff --git a/usr/bin/gitadd b/usr/bin/gitadd new file mode 100755 index 0000000..18380c7 --- /dev/null +++ b/usr/bin/gitadd @@ -0,0 +1,7 @@ +#!/bin/bash +gitadd () +{ + make fclean; + git add . +} +gitadd "$@" diff --git a/usr/bin/gitaddcommit b/usr/bin/gitaddcommit new file mode 100755 index 0000000..70d4af5 --- /dev/null +++ b/usr/bin/gitaddcommit @@ -0,0 +1,11 @@ +#!/bin/bash +gitaddcommit () +{ + gitadd; + if [ -n "$1" ]; then + git commit -m "$1"; + else + git commit; + fi +} +gitaddcommit "$@" diff --git a/usr/bin/gitea_deploy.sh b/usr/bin/gitea_deploy.sh new file mode 100755 index 0000000..0b4d472 --- /dev/null +++ b/usr/bin/gitea_deploy.sh @@ -0,0 +1,33 @@ +cat gitea_deploy.sh +#!/bin/bash +set -e + +# Variables +GITEA_VERSION=1.21.11 +USER_NAME=gitea +GITEA_PORT=9090 +DATA_DIR=/opt/gitea + +# Installer Docker si nécessaire +if ! command -v docker >/dev/null; then + apt update + apt install -y docker.io + systemctl enable docker + systemctl start docker +fi + +# Créer dossier de données +mkdir -p ${DATA_DIR}/{data,config} + +# Lancer Gitea (http://:9090) +docker run -d --name gitea \ + -p ${GITEA_PORT}:3000 \ + -p 2222:22 \ + -v ${DATA_DIR}/data:/data \ + gitea/gitea:${GITEA_VERSION} + +echo "----------------------------------------" +echo "✅ Gitea lancé sur http://:${GITEA_PORT}" +echo "➡️ Identifiants à créer via l'interface web" +echo "➡️ Pour SSH : port 2222 (externe), clé à ajouter via l'UI" +echo "----------------------------------------" diff --git a/usr/bin/gitignore b/usr/bin/gitignore new file mode 100755 index 0000000..21b0bd9 --- /dev/null +++ b/usr/bin/gitignore @@ -0,0 +1,12 @@ +#!/usr/bin/bash + +if [ "$#" -ne 0 ]; then + echo "Usage: $0" + exit 1 +fi + +vim + .gitignore +gitaddcommit .gitignore + +exit 0 + diff --git a/usr/bin/gitlog b/usr/bin/gitlog new file mode 100755 index 0000000..780133e --- /dev/null +++ b/usr/bin/gitlog @@ -0,0 +1,6 @@ +#!/bin/bash +gitlog () +{ + git log --oneline --decorate --graph --all +} +gitlog "$@" diff --git a/usr/bin/gitmain b/usr/bin/gitmain new file mode 100755 index 0000000..9ea533d --- /dev/null +++ b/usr/bin/gitmain @@ -0,0 +1,10 @@ +#!/bin/bash +gitmain () +{ + if [ -z "$1" ]; then + git checkout main; + git reset --hard "$1"; + git push origin main --force; + fi +} +gitmain "$@" diff --git a/usr/bin/gitotal b/usr/bin/gitotal new file mode 100755 index 0000000..f994ae9 --- /dev/null +++ b/usr/bin/gitotal @@ -0,0 +1,10 @@ +#!/bin/bash +gitotal () +{ + gitaddcommit $@; + git pull; + if [ -n "$?" ]; then + git push origin HEAD; + fi +} +gitotal "$@" diff --git a/usr/bin/gnunet-push b/usr/bin/gnunet-push new file mode 100755 index 0000000..70cd454 --- /dev/null +++ b/usr/bin/gnunet-push @@ -0,0 +1,25 @@ +#!/bin/bash +# save_redundant.sh +# Sauvegarde/redondance GNUnet : 3 duplicatas + +# fichier source et clé de publication +SRC="$1" +if [ -z "$SRC" ]; then + echo "Usage: $0 " + exit 1 +fi + +# Tag public de référence +KEYWORD="backup:$(basename "$SRC")" + +# Publier le fichier (ajout au réseau GNUnet FS) +gnunet-publish -n -k "$KEYWORD" -r 3 "$SRC" +# -n : anonyme +# -k : mot-clé (pour retrouver) +# -r : redondance (nb de duplicatas) +# -p : chemin du fichier + +# Vérifie que la donnée est bien publiée +echo "Recherche des duplicatas GNUnet pour $KEYWORD..." +gnunet-search "$KEYWORD" + diff --git a/usr/bin/graphene b/usr/bin/graphene new file mode 100755 index 0000000..494af57 --- /dev/null +++ b/usr/bin/graphene @@ -0,0 +1,16 @@ +#!/usr/bin/bash + +#if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then +# echo "Usage: $0 arg1 [arg2] [arg3]" +# exit 1 +#fi + +echo "Sur pixel 9 taper 7 fois sur le numero de build pour entrer en mode developpeur" + +#pacman -Sy android-udev +#pacman -S android-tools + +#apt install android-sdk-platform-tools-common +#apt install android-sdk-platform-tools-common + +#systemctl stop fwupd.service diff --git a/usr/bin/grepip b/usr/bin/grepip new file mode 100755 index 0000000..a474ed7 --- /dev/null +++ b/usr/bin/grepip @@ -0,0 +1,6 @@ +#!/bin/bash +grepip () +{ + grep --color=auto -Eo $IP_REG $@ | sortu +} +grepip "$@" diff --git a/usr/bin/grepips b/usr/bin/grepips new file mode 100755 index 0000000..08db253 --- /dev/null +++ b/usr/bin/grepips @@ -0,0 +1,6 @@ +#!/usr/bin/bash + +grep -Eo $IP_REG $@ | sortu + +exit 0 + diff --git a/usr/bin/grepkey b/usr/bin/grepkey new file mode 100755 index 0000000..7ba3bad --- /dev/null +++ b/usr/bin/grepkey @@ -0,0 +1,19 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then + echo "Usage: $0 key" + echo "Usage: grep values after key=value" + exit 1 +fi + +awk -v key="$1" '{ + for (i = 1; i <= NF; i++) + if ($i ~ "^"key"=") { + split($i, a, "=") + print a[2] + } +}' # | cut -d\ -f 1 + + +exit 0 + diff --git a/usr/bin/header_awk b/usr/bin/header_awk new file mode 100755 index 0000000..11e6d72 --- /dev/null +++ b/usr/bin/header_awk @@ -0,0 +1,6 @@ +#!/bin/bash +header_awk () +{ + grep --color=auto -RE $CFUNCTION src | cut -d: -f2 | sed s/\$/';'/g +} +header_awk "$@" diff --git a/usr/bin/header_journal b/usr/bin/header_journal new file mode 100755 index 0000000..a0158f3 --- /dev/null +++ b/usr/bin/header_journal @@ -0,0 +1,16 @@ +#!/bin/bash +header_journal () +{ + F_NAME=$1; + . refresh_time + echo "$DATE" >> $F_NAME; + echo "$TIME" >> $F_NAME; + echo "$USER" >> $F_NAME; + echo "$HOST" >> $F_NAME; + echo >> $F_NAME; + echo "###############################################" >> $F_NAME; + echo >> $F_NAME; + echo "$F_NAME" >> $F_NAME; + echo >> $F_NAME +} +header_journal "$@" diff --git a/usr/bin/history_full b/usr/bin/history_full new file mode 100755 index 0000000..2da8b02 --- /dev/null +++ b/usr/bin/history_full @@ -0,0 +1,13 @@ +#!/bin/bash +history_full () +{ + HIST_FILE=~/.history; + while read LINE; do + if [ -n "$(echo "$LINE" | grep '^#')" ]; then + date -d "$(echo $LINE | sed 's/\#/@/g')"; + else + echo "$LINE"; + fi; + done < $HIST_FILE +} +history_full "$@" diff --git a/usr/bin/ipinfo b/usr/bin/ipinfo new file mode 100755 index 0000000..d260991 --- /dev/null +++ b/usr/bin/ipinfo @@ -0,0 +1,6 @@ +#!/bin/bash +ipinfo () +{ + curl https://ipinfo.io/$1 +} +ipinfo "$@" diff --git a/usr/bin/journal b/usr/bin/journal new file mode 100755 index 0000000..b00ce10 --- /dev/null +++ b/usr/bin/journal @@ -0,0 +1,44 @@ +#!/bin/bash +journal () +{ + . refresh_time; + DIR_ORIGINAL=$PWD; + DIR="$HOME/journal/"; + DATE_DIR="$YEAR/$MONTH/$DAY"; + if [ "$#" -eq 0 ]; then + echo "Usage: $0 [ subfolder ] < file >"; + echo "default path is $DIR"; + echo "default file name is $F_NAME"; + return 1; + fi; + if [ "$#" -eq 1 ]; then + LN_DIR="fouretout"; + F_NAME=$1; + fi; + if [ "$#" -eq 2 ]; then + LN_DIR="$1"; + F_NAME=$2; + else + echo check args + return 1; + fi; + mkdir -p $DIR/$HOST + F_NAME+=".md"; + cd $DIR; + PATH_="${DATE_DIR}/${LN_DIR}"; + mkdir -p "$PATH_"; + FILE="${PATH_}/${F_NAME}"; + header_journal $FILE; + echo "header done" + if commit_if_modified $FILE; then + mkdir -p "$DIR/$HOST/$LN_DIR"; + ln -P "$FILE" "$DIR/$HOST/$LN_DIR"; + git add . ; + git commit -m " -> linked"; + else + rm $FILE; + rmdir -p "${PATH_}"; + fi; + cd $DIR_ORIGINAL +} +journal "$@" diff --git a/usr/bin/journal-perso b/usr/bin/journal-perso new file mode 100755 index 0000000..9ea13c7 --- /dev/null +++ b/usr/bin/journal-perso @@ -0,0 +1,42 @@ +#!/bin/bash +journal-perso () +{ + . . refresh_time; + DIR_ORIGINAL=$PWD; + DIR=$PERSO_DIR; + DATE_DIR="$YEAR/$MONTH/$DAY"; + if [ "$#" -eq 0 ]; then + echo "Usage: $0 [ subfolder ] < file >"; + echo "default path is $DIR"; + echo "default file name is $F_NAME"; + return 1; + fi; + if [ "$#" -eq 1 ]; then + LN_DIR="fouretout"; + F_NAME=$1; + fi; + if [ "$#" -eq 2 ]; then + LN_DIR="$1"; + F_NAME=$2; + else + return 1; + fi; + F_NAME+=".md"; + cd $DIR; + PATH_="${DATE_DIR}/${LN_DIR}"; + mkdir -p "$PATH_"; + FILE="${PATH_}/${F_NAME}"; + header_journal $FILE; + if commit_if_modified $FILE; then + mkdir -p "$DIR/$LN_DIR"; + ln -P "$FILE" "$DIR/$LN_DIR/"; + git add "$DIR/$LN_DIR/$FILE"; + git commit -m "-> $FILE linked"; + else + rm $FILE; + rmdir -p "${PATH_}"; + fi; + cd $DIR_ORIGINAL +} + +journal-perso "$@" diff --git a/usr/bin/keygen-repo b/usr/bin/keygen-repo new file mode 100755 index 0000000..43e31ac --- /dev/null +++ b/usr/bin/keygen-repo @@ -0,0 +1,37 @@ +#!/bin/bash + +REPO_PATH="$1" +HOST_ALIAS=${2:-""} # optional, defaults to domain in remote URL +PROFILE_ALIAS=${3:-"$USER"} +PASSPHRASE=${4:-""} + +[ -z "$REPO_PATH" ] && { echo "Usage: $0 /path/to/repo"; exit 1; } + +cd "$REPO_PATH" || exit 1 + +KEY_PATH="$HOME/.ssh/$(basename "$REPO_PATH")_id_ed25519" +ssh-keygen -t ed25519 -f "$KEY_PATH" -C "$(basename "$REPO_PATH")" -N "$PASSPHRASE" + +eval "$(ssh-agent -s)" +ssh-add "$KEY_PATH" + +REMOTE_URL=$(git remote get-url origin) + +# Extract domain from remote URL +if [[ "$REMOTE_URL" =~ ([^/:]+(:[0-9]+)?)[/:].* ]]; then + DOMAIN="${BASH_REMATCH[1]}" +else + echo "Could not parse remote domain. Please update manually." + exit 1 +fi + +# Use provided host alias if given +HOST_TO_USE=${HOST_ALIAS:-$DOMAIN} + +REPO_NAME=$(basename "$REPO_PATH") +git remote set-url origin git@$HOST_TO_USE:$PROFILE_ALIAS/$REPO_NAME.git +echo "Remote URL updated to use SSH key for this repo." + +cd - +exit 0 + diff --git a/usr/bin/kill_all b/usr/bin/kill_all new file mode 100755 index 0000000..d68afb4 --- /dev/null +++ b/usr/bin/kill_all @@ -0,0 +1,11 @@ +#!/bin/bash +kill_all () +{ + if [ -z "$1" ]; then + echo "Usage: $0 "; + exit 1; + fi; + KEYWORD="$1"; + ps aux | grep --color=auto "$KEYWORD" | grep --color=auto -v "grep" | awk '{print $2}' | xargs -r kill -9 +} +kill_all "$@" diff --git a/usr/bin/lemmatizer.py b/usr/bin/lemmatizer.py new file mode 100755 index 0000000..1973374 --- /dev/null +++ b/usr/bin/lemmatizer.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +import sys +import spacy + +# Charger les modèles français et anglais +nlp_fr = spacy.load("fr_core_news_sm") +nlp_en = spacy.load("en_core_web_sm") + +# Lire le texte depuis stdin +text = sys.stdin.read().strip() + +# Détecter la langue (simple : regarder les caractères ou demander en argument) +# Ici, on choisit automatiquement en fonction des mots +# -> si beaucoup de mots anglais, on prend anglais, sinon français +words = text.split() +english_words = sum(1 for w in words if w.lower() in ["the","is","are","i","you","we","and"]) +nlp = nlp_en if english_words > len(words) / 2 else nlp_fr + +# Lemmatiser +doc = nlp(text) +lemmes = [token.lemma_ for token in doc if token.is_alpha] + +print(" ".join(lemmes)) + + + + diff --git a/usr/bin/m b/usr/bin/m new file mode 100755 index 0000000..7193828 --- /dev/null +++ b/usr/bin/m @@ -0,0 +1,15 @@ +#!/usr/bin/bash + +NAME+=$(dmesg | tail | grep -o sd[a-z] | tail -1) +NAME+=1 +DEV=/dev/${NAME} +MNT_PT=/mnt/$NAME + +echo "mount dev: $DEV at $MNT_PT" + +mkdir $MNT_PT +mount $DEV $MNT_PT +cd $MNT_PT + +exit 0 + diff --git a/usr/bin/mediaspi b/usr/bin/mediaspi new file mode 100755 index 0000000..b467a09 --- /dev/null +++ b/usr/bin/mediaspi @@ -0,0 +1,21 @@ +#!/bin/bash +mediaspi () +{ + if [ -z $1 ]; then + echo "usage: $0 $DIR_NAME"; + return 1; + fi; + BINAME="collector_bin"; + DEST="$HOME/perso/${BINAME}"; + DIR="${1}"; + mkdir -p $DEST; + mkdir $DIR; + if [ $? -ne 0 ]; then + echo "$DIR exists, must be deleted (will be anyway)"; + return 1; + fi; + find . -type f -regextype egrep -iregex ".*$MEDIA_REG" -exec cp --parents -u {} -t $DIR \;; + cp -apu $DIR -t $DEST; + rm -rf $DIR +} +mediaspi "$@" diff --git a/usr/bin/mobian_dl b/usr/bin/mobian_dl new file mode 100755 index 0000000..9643b94 --- /dev/null +++ b/usr/bin/mobian_dl @@ -0,0 +1,71 @@ +#!/bin/bash +# mobian_vm_signed.sh +# Télécharge dernière image Mobian signée, lance VM, sauvegarde incrémentale + +set -euo pipefail + +BASE_URL="${1:-https://images.mobian.org/amd64/weekly/}" +WORKDIR="${2:-/var/lib/mobian_vm}" +BACKUPDIR="${3:-/var/backups/mobian}" + +mkdir -p "$WORKDIR" "$BACKUPDIR" +cd "$WORKDIR" + +echo "[1] Recherche dernière image signée" +INDEX=$(wget -qO- "$BASE_URL") +# cherche uniquement les images avec .img.xz et .sha256 existants +IMG_NAME=$(echo "$INDEX" | grep -oP 'mobian-amd64-\d{6,8}\.img\.xz' | sort | tail -n1) + +if [ -z "$IMG_NAME" ]; then + echo "Aucune image signée trouvée dans $BASE_URL" + exit 1 +fi + +echo "→ Image trouvée: $IMG_NAME" + +# Téléchargement +echo "[2] Téléchargement image + signatures" +wget -N "$BASE_URL$IMG_NAME" \ + "$BASE_URL$IMG_NAME.sha256" \ + "$BASE_URL$IMG_NAME.asc" + +# Vérification SHA256 +echo "[3] Vérification SHA256" +sha256sum -c "$IMG_NAME.sha256" + +# Vérification GPG +echo "[4] Vérification GPG" +gpg --keyserver keyserver.ubuntu.com --recv-keys 0x1CE2AFD36DBA9F48 +gpg --verify "$IMG_NAME.asc" "$IMG_NAME" + +RAW_IMG="${IMG_NAME%.xz}" + +# Extraction si nécessaire +if [ ! -f "$RAW_IMG" ]; then + xz -dk "$IMG_NAME" +fi + +## Arrêt éventuelle ancienne VM +#pkill -f "qemu-system-x86_64.*$RAW_IMG" || true +# +## Lancement VM +#echo "[5] Lancement VM" +#nohup qemu-system-x86_64 \ +# -m 2048 -smp 2 \ +# -drive file="$RAW_IMG",format=raw \ +# -nic user,hostfwd=tcp::2222-:22 \ +# -nographic >"$WORKDIR/qemu.log" 2>&1 & +# +## Sauvegarde incrémentale +#echo "[6] Sauvegarde incrémentale" +#TODAY=$(date +%F) +#rsync -a --link-dest="$BACKUPDIR/latest" \ +# "$RAW_IMG" \ +# "$BACKUPDIR/$TODAY/" +#ln -sfn "$BACKUPDIR/$TODAY" "$BACKUPDIR/latest" +# +#echo "[OK] VM active sur port 2222 (SSH/X11)." +#echo "Depuis smartphone :" +#echo " ssh -p 2222 -C -X user@serveur" +#echo "Puis lancer startlxqt ou autre session graphique." + diff --git a/usr/bin/monip b/usr/bin/monip new file mode 100755 index 0000000..f68f61f --- /dev/null +++ b/usr/bin/monip @@ -0,0 +1,6 @@ +#!/bin/bash +monip () +{ + curl ifconfig.me +} +monip "$@" diff --git a/usr/bin/netstat_tunlp b/usr/bin/netstat_tunlp new file mode 100755 index 0000000..2aafd73 --- /dev/null +++ b/usr/bin/netstat_tunlp @@ -0,0 +1,6 @@ +#!/bin/bash +netstat_tunlp () +{ + netstat -tunlp +} +netstat_tunlp "$@" diff --git a/usr/bin/nmap-http b/usr/bin/nmap-http new file mode 100755 index 0000000..e98c228 --- /dev/null +++ b/usr/bin/nmap-http @@ -0,0 +1,11 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] ; then + echo "Usage: $0 ip [polite2]" + exit 1 +fi + +nmap --script -T3 http-enum $1 + +exit 0 + diff --git a/usr/bin/nmap-list b/usr/bin/nmap-list new file mode 100755 index 0000000..165ae17 --- /dev/null +++ b/usr/bin/nmap-list @@ -0,0 +1,26 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then + echo "Usage: $0 arg1 [arg2] [arg3]" + exit 1 +fi +FILE=${1} +DIR=${2:-"nmap-list"} + +echo saving in $DIR + +mkdir -p "${DIR}" + +while IFS= read -r line; do + IP_ADDR=$(echo $line | grep -Eo $IP_REG) + F_OUT=$DIR/$IP_ADDR + echo request $IP_ADDR + if [ -n "$IP_ADDR" ] ; then + nmap -A -T 2 -Pn "$IP_ADDR" | tee "$F_OUT" + whois "$IP_ADDR" | tee "$F_OUT.whois" + echo done + fi +done < "$FILE" + +exit 0 + diff --git a/usr/bin/nmap-port b/usr/bin/nmap-port new file mode 100755 index 0000000..9187553 --- /dev/null +++ b/usr/bin/nmap-port @@ -0,0 +1,16 @@ +#!/usr/bin/bash + +if [ "$#" -ne 2 ] ; then + echo "Usage: $0 IP port" + exit 1 +fi + +IP=$1 +PORT=$2 + +nmap -Pn -sV -p "$PORT" --open "$TARGET" + +nmap --script check-port --script-args checkport.port=$PORT -p $PORT $IP + +exit 0 + diff --git a/usr/bin/nmap_full b/usr/bin/nmap_full new file mode 100755 index 0000000..e438293 --- /dev/null +++ b/usr/bin/nmap_full @@ -0,0 +1,6 @@ +#!/bin/bash +nmap_full () +{ + sudo nmap --scanflags URGACKPSHRSTSYNFIN $@ +} +nmap_full "$@" diff --git a/usr/bin/nmap_sA b/usr/bin/nmap_sA new file mode 100755 index 0000000..a98376e --- /dev/null +++ b/usr/bin/nmap_sA @@ -0,0 +1,6 @@ +#!/bin/bash +nmap_sA () +{ + nmap -Pn -sA --reason $@ +} +nmap_sA "$@" diff --git a/usr/bin/nmap_script.sh b/usr/bin/nmap_script.sh new file mode 100755 index 0000000..8d663be --- /dev/null +++ b/usr/bin/nmap_script.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +if [ -z "$1" ] ; then echo "no args" ; exit 1 ; fi + +TARGET=$1 +DIR="$HOME/journal/net/scan/$2" +[[ "$DIR" != */ ]] && DIR="$DIR/" +OUTPUT_DIR=$DIR"${TARGET}_$(date +%F_%H-%M-%S).nmap" + +mkdir -p "$OUTPUT_DIR" + +log() { + echo "[+] $1" + echo "[+] $1" >> "$OUTPUT_DIR/scan.log" +} + +log "Target: $TARGET" + +### 1. Passive recon +log "DNS & WHOIS" +dig +short "$TARGET" > "$OUTPUT_DIR/dns.txt" +whois "$TARGET" > "$OUTPUT_DIR/whois.txt" +nslookup "$TARGET" > "$OUTPUT_DIR/nslookup.txt" + +log "Traceroute" +traceroute "$TARGET" > "$OUTPUT_DIR/traceroute.txt" + +# Détection IPv4 / IPv6 +IPV4=$(dig +short A "$TARGET" | head -n1) +IPV6=$(dig +short AAAA "$TARGET" | head -n1) + +scan_block() { + local mode=$1 # "IPv4" ou "IPv6" + local opt=$2 # "" ou "-6" + + log "=== $mode Scans ===" + + log "Fast TCP Scan (top 100 ports)" + sudo nmap $opt -Pn -sS -sV --top-ports 100 -T2 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_fast_tcp.txt" + + log "Full TCP Scan (all 65535 ports)" + sudo nmap $opt -Pn -sS -p- -T3 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_full_tcp.txt" + + log "UDP Scan (top 50 ports)" + sudo nmap $opt -Pn -sU --top-ports 50 -T4 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_udp.txt" + + log "SCTP Init Scan (top 50 ports)" + sudo nmap $opt -Pn -sY --top-ports 50 -T3 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_sctp.txt" + + log "Service Detection (all protocols)" + sudo nmap $opt -Pn -sV -p- -sS -sU -T2 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_service.txt" + + log "OS Detection" + sudo nmap $opt -Pn -O -A -T2 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_os.txt" + + log "Nmap Vulnerability Scripts" + sudo nmap $opt -Pn --script vuln -T2 "$TARGET" -oN "$OUTPUT_DIR/nmap_${mode}_vuln.txt" +} + +### 2. Lancer scans selon ce qui est dispo +if [ -n "$IPV4" ]; then + log "IPv4 detected: $IPV4" + scan_block "ipv4" "" +else + log "No IPv4 found" +fi + +if [ -n "$IPV6" ]; then + log "IPv6 detected: $IPV6" + scan_block "ipv6" "-6" +else + log "No IPv6 found" +fi + +### 3. Fin +log "Scan completed. Results in $OUTPUT_DIR/" + +# Hook perso +source "$HOME/.bashrc" +journal "$OUTPUT_DIR" README + diff --git a/usr/bin/nmap_ssh_brute b/usr/bin/nmap_ssh_brute new file mode 100755 index 0000000..dabae03 --- /dev/null +++ b/usr/bin/nmap_ssh_brute @@ -0,0 +1,6 @@ +#!/bin/bash +nmap_ssh_brute () +{ + nmap --script "ssh-brute" $1 +} +nmap_ssh_brute "$@" diff --git a/usr/bin/nmap_version b/usr/bin/nmap_version new file mode 100755 index 0000000..a2c50b1 --- /dev/null +++ b/usr/bin/nmap_version @@ -0,0 +1,7 @@ +#!/bin/bash +nmap_version () +{ + echo "run : nmap -sV --version-intensity 9 -O -sC $@" + nmap -sV --version-intensity 9 -O -sC $@ +} +nmap_version "$@" diff --git a/usr/bin/normi b/usr/bin/normi new file mode 100755 index 0000000..25e40d7 --- /dev/null +++ b/usr/bin/normi @@ -0,0 +1,6 @@ +#!/bin/bash +normi () +{ + norminette -R CheckForbiddenSourceHeader -R CheckDefine $1 +} +normi "$@" diff --git a/usr/bin/p b/usr/bin/p new file mode 100755 index 0000000..4d79cae --- /dev/null +++ b/usr/bin/p @@ -0,0 +1,3 @@ +#!/usr/bin/bash + +ping -c1 9.9.9.9 diff --git a/usr/bin/pacmaninstall b/usr/bin/pacmaninstall new file mode 100755 index 0000000..72ac495 --- /dev/null +++ b/usr/bin/pacmaninstall @@ -0,0 +1,6 @@ +#!/usr/bin/bash +cd $MACHINE_DIR +commit_if_modified $MACHINE_DIR/install/pacman.sh +cd - +exit 0 + diff --git a/usr/bin/portlsof b/usr/bin/portlsof new file mode 100755 index 0000000..74e179a --- /dev/null +++ b/usr/bin/portlsof @@ -0,0 +1,8 @@ +#!/usr/bin/bash + +echo read open port and lsof try to return the associated process + +ss -tunl | awk '{if (NR != 1) print $5}' | awk -F: '{print $NF}' | sort | uniq | xargs -I PORT bash -c "echo port: PORT && lsof -i :PORT | awk '{if (NR != 1) print $NR}'" + +exit 0 + diff --git a/usr/bin/post-chroot-iso b/usr/bin/post-chroot-iso new file mode 100755 index 0000000..d7f5d1a --- /dev/null +++ b/usr/bin/post-chroot-iso @@ -0,0 +1,18 @@ +#!/usr/bin/bash + +ISO-${1:-"edited_iso"} +WORKDIR=$(1:-"iso_edit"} + +if [ "$#" -lt 1 ] ; then + echo "Usage: $0 name [iso_edit] + note: delete iso_edit and convert it in the + named file" + exit 1 +fi + +umount "$WORKDIR"/{proc,sys,dev} +genisoimage -o $ISO -V "CUSTOM" -R -J "$WORKDIR" +echo "note: genisoimage come from cdrkit package" + +exit 0 + diff --git a/usr/bin/ps_parents b/usr/bin/ps_parents new file mode 100755 index 0000000..9ba9767 --- /dev/null +++ b/usr/bin/ps_parents @@ -0,0 +1,14 @@ +#!/bin/bash +ps_parents () +{ + if [ "$#" -ne 1 ]; then + echo "Usage: $0 "; + return 1; + fi; + pid=$1; + while [ "$pid" -ne 1 ]; do + ps -p $pid -o pid=,ppid=,cmd=; + pid=$(ps -p $pid -o ppid= --no-headers); + done +} +ps_parents "$@" diff --git a/usr/bin/py_test b/usr/bin/py_test new file mode 100755 index 0000000..35bacde --- /dev/null +++ b/usr/bin/py_test @@ -0,0 +1,9 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] + echo "Usage: $0 arg1 [arg2] [arg3]" + exit 1 +fi + +shift +python -m py_compile $@ diff --git a/usr/bin/qtileconf b/usr/bin/qtileconf new file mode 100755 index 0000000..aca7481 --- /dev/null +++ b/usr/bin/qtileconf @@ -0,0 +1,4 @@ +#!/usr/bin/bash +vim ~/.config/qtile/config.py +exit 0 + diff --git a/usr/bin/refresh_time b/usr/bin/refresh_time new file mode 100755 index 0000000..0ec2d46 --- /dev/null +++ b/usr/bin/refresh_time @@ -0,0 +1,4 @@ +#!/bin/bash + +export DATE=$(date +"%y%m%d"); +export TIME=$(date +"%T") diff --git a/usr/bin/report-cmd b/usr/bin/report-cmd new file mode 100755 index 0000000..54b052b --- /dev/null +++ b/usr/bin/report-cmd @@ -0,0 +1,17 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] ; then + echo "Usage: $0 cmd [outfile]" + exit 1 +fi + + CMD="$1" + OUT=${2:-"$(echo $CMD | sed s/ /_/g)"} + #DIR=$(realpath $OUT) + #mkdir -p $DIR + header_journal "$OUT" + echo "== $CMD ==" | tee -a "$OUT" + eval "$CMD" 2>&1 | tee -a "$OUT" + +exit 0 + diff --git a/usr/bin/report-ipv6 b/usr/bin/report-ipv6 new file mode 100755 index 0000000..a91e46b --- /dev/null +++ b/usr/bin/report-ipv6 @@ -0,0 +1,37 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then + echo "Usage: $0 arg1 [arg2] [arg3]" + exit 1 +fi +#!/bin/bash + +IP="$1" +DIR="${2:-${IP}_report}" + +mkdir -p "$DIR" +cd $DIR + +#report-cmd "dig AAAA $IP" +# +#report-cmd "dig -x $IP" +#report-cmd "host $IP" + +report-cmd "curl -s https://ipinfo.io/$IP" ipinfo +report-cmd "curl -s https://ipapi.co/$IP/json/" ipapi + +#report-cmd "sipcalc $IP" +#report-cmd "ipv6calc --in ipv6addr $IP" +# +#report-cmd "traceroute6 $IP" +#report-cmd "tracepath6 $IP" + +#report-cmd "curl -s https://api.bgpview.io/ip/$IP" +#report-cmd "curl -s 'https://stat.ripe.net/data/prefix-overview/data.json?resource=$IP'" +# +#report-cmd "nmap -6 $IP" + +cd - + +exit 0 + diff --git a/usr/bin/report_crash b/usr/bin/report_crash new file mode 100755 index 0000000..b54eead --- /dev/null +++ b/usr/bin/report_crash @@ -0,0 +1,30 @@ +#!/bin/bash +report_crash () +{ + . refresh_time; + NAME=$1; + TAIL_SIZE="100"; + DIR_ORIGINAL=$PWD; + CRASH_DIR="$(echo ${DATE}_${TIME} | sed 's/:/-/g')"; + F_NAME="${NAME}.crash"; + DIR_RELATIVE="$HOME/journal/sysadmin/crash"; + DIR_RELATIVE+="/${CRASH_DIR}"; + if [ "$#" -ne 1 ]; then + echo "Usage: $0 FILE_NAME"; + echo "default path is $DIR_RELATIVE/FILE_NAME.crash"; + echo "write log outputs"; + return 1; + fi; + mkdir -p $DIR_RELATIVE; + cd $DIR_RELATIVE; + if [ -f $F_NAME ]; then + BCK="/tmp/$F_NAME.backup"; + echo "File exists moved to $BCK"; + mv $F_NAME $BCK; + fi; + header_journal $F_NAME; + journalctl_prettyfy "100" "1" "0" "$F_NAME"; + commit_if_modified "$F_NAME" "DELETE_IF_NOT_MODIFIED"; + cd $DIR_ORIGINAL +} +report_crash "$@" diff --git a/usr/bin/report_last_boot b/usr/bin/report_last_boot new file mode 100755 index 0000000..d27b106 --- /dev/null +++ b/usr/bin/report_last_boot @@ -0,0 +1,26 @@ +#!/bin/bash +report_last_boot () +{ + . refresh_time; + NAME=$1; + DIR_ORIGINAL=$PWD; + CRASH_DIR="$(echo ${DATE}_${TIME} | sed 's/:/-/g')"; + F_NAME="${NAME}.crash"; + DIR_RELATIVE="$HOME/journal/sysadmin/crash/reboot"; + DIR_RELATIVE+="/${CRASH_DIR}"; + if [ "$#" -ne 1 ]; then + echo "Usage: $0 FILE_NAME"; + echo "default path is $DIR_RELATIVE/${CRASH_DIR}/FILE_NAME.crash"; + echo "write log outputs"; + return 1; + fi; + mkdir -p $DIR_RELATIVE; + cd $DIR_RELATIVE; + header_journal $F_NAME; + # journalctl_prettyfy N_TAIL MIN_OCC BOOT_NB F_NAME; + journalctl_prettyfy 500 5 1 $F_NAME; + journalctl_prettyfy 10000 5 0 $F_NAME; + commit_if_modified "$F_NAME" "DELETE_IF_NOT_MODIFIED"; + cd $DIR_ORIGINAL +} +report_last_boot "$@" diff --git a/usr/bin/rsa-sign b/usr/bin/rsa-sign new file mode 100755 index 0000000..f97fdd9 --- /dev/null +++ b/usr/bin/rsa-sign @@ -0,0 +1,7 @@ +#!/usr/bin/bash + +KEY="$1" +MSG="$2" +OUT="$3" + +echo "$MSG" | openssl dgst -sha256 -sign "$PRIVKEY" --out "$OUT" diff --git a/usr/bin/screen-double b/usr/bin/screen-double new file mode 100755 index 0000000..823cf8a --- /dev/null +++ b/usr/bin/screen-double @@ -0,0 +1,5 @@ +#!/usr/bin/bash +xrandr --output HDMI-1 --primary --mode 1920x1080 --output eDP-1 --mode 1600x900 --right-of HDMI-1 +echo "xrandr --output HDMI-1 --primary --mode 1920x1080 --output eDP-1 --mode 1600x900 --right-of HDMI-1" +exit 0 + diff --git a/usr/bin/sign-arch b/usr/bin/sign-arch new file mode 100755 index 0000000..49edd95 --- /dev/null +++ b/usr/bin/sign-arch @@ -0,0 +1,39 @@ +#!/usr/bin/bash + +DIR=signing_dir +FILE=arch.iso + +if [ "$#" -ne 1 ] ; then + echo "Usage: $0 iso" + echo works in $DIR + echo copy iso as $FILE + exit 1 +fi + +mkdir $DIR + +cp $1 $DIR/$FILE + +cd $DIR + +osirrox -indev $FILE \ + -extract_boot_images ./ \ + -cpx /arch/boot/x86_64/vmlinuz-linux \ + /EFI/BOOT/BOOTx64.EFI \ + /EFI/BOOT/BOOTIA32.EFI \ + /shellx64.efi \ + /shellia32.efi ./ + +chmod +w BOOTx64.EFI BOOTIA32.EFI shellx64.efi shellia32.efi vmlinuz-linux + + +sbsign --key db.key --cert db.crt --output BOOTx64.EFI BOOTx64.EFI +sbsign --key db.key --cert db.crt --output BOOTIA32.EFI BOOTIA32.EFI +sbsign --key db.key --cert db.crt --output shellx64.efi shellx64.efi +sbsign --key db.key --cert db.crt --output shellia32.efi shellia32.efi +sbsign --key db.key --cert db.crt --output vmlinuz-linux vmlinuz-linux + +cd - + +exit 0 + diff --git a/usr/bin/sign-efi b/usr/bin/sign-efi new file mode 100755 index 0000000..dc851ce --- /dev/null +++ b/usr/bin/sign-efi @@ -0,0 +1,25 @@ +#!/usr/bin/bash + +EFI=${1:-"shim.efi"} +NAME=${2:-"MOK"} +SIGNED_EFI=${3:-"$(echo $EFI | sed 's/.efi/-signed.efi/')"} +DB_KEY=${4:-"${NAME}.key"} +DB_CERT=${5:-"${NAME}.crt"} + +if [ "$#" -eq 0 ] ; then + echo ''' + + EFI=${1:-"shim.efi"} + NAME=${2:-"MOK"} + SIGNED_EFI=${3:-"$(echo $EFI | sed 's/.efi/-signed.efi/')"} + DB_KEY=${4:-"${NAME}.key"} + DB_CERT=${5:-"${NAME}.crt)"} + + ''' + echo "sbsign --key $DB_KEY --cert $DB_CERT --output $SIGNED_EFI $EFI" + echo "Usage: $0 efi" + exit 1 +fi + +sbsign --key $DB_KEY --cert $DB_CERT --output $SIGNED_EFI $EFI + diff --git a/usr/bin/sign-wiki b/usr/bin/sign-wiki new file mode 100755 index 0000000..ebed177 --- /dev/null +++ b/usr/bin/sign-wiki @@ -0,0 +1,36 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then + echo "Usage: $0 arg1 [arg2] [arg3]" + exit 1 +fi + +uuidgen --random > guid.txt + +openssl req -new -x509 -newkey rsa:2048 -subj "/CN=My Platform Key/" -keyout pk.key -out pk.crt -days 3650 -nodes -sha256 +openssl req -new -x509 -newkey rsa:2048 -subj "/CN=My Key Exchange Key/" -keyout kek.key -out kek.crt -days 3650 -nodes -sha256 +openssl req -new -x509 -newkey rsa:2048 -subj "/CN=My Signature DB Key/" -keyout db.key -out db.crt -days 3650 -nodes -sha256 + +uuidgen --random > guid.txt +sign-efi-sig-list -k pk.key -c pk.crt PK pk.esl pk.auth + +cert-to-efi-sig-list -g "$(< guid.txt)" kek.crt kek.esl +cert-to-efi-sig-list -g "$(< guid.txt)" db.crt db.esl + +with created private key: + +sign-efi-sig-list -k pk.key -c pk.crt PK pk.esl pk.auth + +cert-to-efi-sig-list -g "$(< guid.txt)" kek.crt kek.esl +cert-to-efi-sig-list -g "$(< guid.txt)" db.crt db.esl + +cat old_KEK.esl kek.esl > combined_KEK.esl +cat old_db.esl db.esl > combined_db.esl + +efi-updatevar -e -f old_dbx.esl dbx +efi-updatevar -e -f combined_db.esl db +efi-updatevar -e -f combined_KEK.esl KEK +efi-updatevar -f pk.auth PK + +exit 0 + diff --git a/usr/bin/sortu b/usr/bin/sortu new file mode 100755 index 0000000..cbf2128 --- /dev/null +++ b/usr/bin/sortu @@ -0,0 +1,6 @@ +#!/bin/bash +sortu () +{ + sort | uniq -c | sort -n +} +sortu "$@" diff --git a/usr/bin/sound-down b/usr/bin/sound-down new file mode 100755 index 0000000..cf78e4a --- /dev/null +++ b/usr/bin/sound-down @@ -0,0 +1,2 @@ +#!/usr/bin/bash +pamixer -d 10 diff --git a/usr/bin/sound-up b/usr/bin/sound-up new file mode 100755 index 0000000..56389fa --- /dev/null +++ b/usr/bin/sound-up @@ -0,0 +1,2 @@ +#!/usr/bin/bash +pamixer -i 10 diff --git a/usr/bin/ss-greppb b/usr/bin/ss-greppb new file mode 100755 index 0000000..e7cfe80 --- /dev/null +++ b/usr/bin/ss-greppb @@ -0,0 +1,4 @@ +#!/usr/bin/bash + +ss -tanp | awk '$5=="-1" || $6=="-1" {print $7}' + diff --git a/usr/bin/status b/usr/bin/status new file mode 100755 index 0000000..c91d828 --- /dev/null +++ b/usr/bin/status @@ -0,0 +1,6 @@ +#!/usr/bin/bash + +vim $NET_STATUS + +exit 0 + diff --git a/usr/bin/tail-dl.sh b/usr/bin/tail-dl.sh new file mode 100755 index 0000000..61fba3c --- /dev/null +++ b/usr/bin/tail-dl.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -euo pipefail + +GNUPGHOME=$(mktemp -d) +export GNUPGHOME +trap 'rm -rf "$GNUPGHOME"' EXIT + +echo "Fetching metadata..." +LATEST_JSON=$(curl -fsSL https://tails.net/install/v2/Tails/amd64/stable/latest.json) + +IMG_URL=$(echo "$LATEST_JSON" | jq -r '.installations[]."installation-paths"[] | select(.type=="img") | .["target-files"][0].url') +SIG_URL="${IMG_URL}.sig" + +echo "Image URL: $IMG_URL" +curl -fsSLO "$IMG_URL" + +echo "Signature URL: $SIG_URL" +curl -fsSLO "$SIG_URL" +curl -fsSLO https://tails.net/tails-signing.key + +echo "import signin keys" +gpg --import tails-signing.key + +echo +echo "Fingerprint of imported key:" +gpg --fingerprint + +echo +echo "Verifying signature..." +TZ=UTC gpg --verify "$(basename "$SIG_URL")" "$(basename "$IMG_URL")" + diff --git a/usr/bin/tcp-manual-scan b/usr/bin/tcp-manual-scan new file mode 100755 index 0000000..8c52208 --- /dev/null +++ b/usr/bin/tcp-manual-scan @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +import socket +import argparse + +def scan(host, port, banner, timeout): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(timeout) + try: + err = s.connect_ex((host, port)) + if err == 111: + return "closed", b"" + if err != 0: + return "filtered", b"" + try: + s.sendall(banner) + except: + print("Error sending") + try: + data = s.recv(1024) + except: + data = b"error receiving" + return "open", data + finally: + s.close() + +def main(): + p = argparse.ArgumentParser() + p.add_argument("host") + p.add_argument("-P", "--ports", default="22,80,443") + p.add_argument("-b", "--banner", default="GET / ") + p.add_argument("-t", "--timeout", type=float, default=1.0) + a = p.parse_args() + + ports = [int(x) for x in a.ports.split(",") if x.strip()] + banner = a.banner.encode() + + for port in ports: + state, data = scan(a.host, port, banner, a.timeout) + if state == "open": + print(f"{port} open {data.decode('utf-8', 'replace').strip()}") + else: + print(f"{port} {state}") + +if __name__ == "__main__": + main() + diff --git a/usr/bin/tcpd b/usr/bin/tcpd new file mode 100755 index 0000000..73eb956 --- /dev/null +++ b/usr/bin/tcpd @@ -0,0 +1,41 @@ +#!/usr/bin/bash + +DIR=${1:-"$LOG_CONN_DIR"} +SUB_DIR=${2:-$(date "+%y%m%d")} +DIR="$DIR/$SUB_DIR" +NAME=${2:-"dflt"} +NAME=$(echo $(date +"%y%m%d")-$(date +"%T").$NAME | sed "s/:/_/g") +FILE=$DIR/$NAME + +echo "File at $FILE" +if [ "$#" -lt 1 ] ; then + echo "usage $0 filename" + echo "File at $FILE" + exit 1 +fi + +mkdir -p $DIR + +echo "File at $FILE" + +#DEVICE=$(ip addr | grep -v DOWN | grep -E "^[0-9]" | awk -F':' '{print $2}' | grep -v lo) +#NB_DEVICES="$(echo ${DEVICE} | awk '{print NF}')" +# +#if [ $NB_DEVICES -lt "1" ] ; then +# echo no device +# echo $DEVICE +# exit 1 +#elif [ $NB_DEVICES -gt "1" ] ; then +# echo several devices, precise it using '$2': +# echo $DEVICE +# exit 1 +#fi + +echo 'DEVICE='$DEVICE +echo + +tcpdump -U -n | tee -a $FILE.log +tcpdump -U -w $FILE.pcap + +exit 1 + diff --git a/usr/bin/to_mp3 b/usr/bin/to_mp3 new file mode 100755 index 0000000..c809e02 --- /dev/null +++ b/usr/bin/to_mp3 @@ -0,0 +1,12 @@ +#!/bin/bash +to_mp3 () +{ + for file in "$@"; + do + MP3_NAME=${file%.*}.mp3; + echo $file; + echo; + ffmpeg -i $file -vn -b:a 192k "$MP3_NAME"; + done +} +to_mp3 "$@" diff --git a/usr/bin/to_wav b/usr/bin/to_wav new file mode 100755 index 0000000..ccefc99 --- /dev/null +++ b/usr/bin/to_wav @@ -0,0 +1,13 @@ +#!/bin/bash +to_wav () +{ + OUTDIR_NAME="wav_files"; + for file in "$@"; + do + WAV_NAME=${file%.*}.wav; + echo $file; + echo; + ffmpeg -i $file -ar 16000 -ac 1 "$WAV_NAME"; + done +} +to_wav "$@" diff --git a/usr/bin/usb-reset b/usr/bin/usb-reset new file mode 100755 index 0000000..6f4ec19 --- /dev/null +++ b/usr/bin/usb-reset @@ -0,0 +1,42 @@ +#!/usr/bin/bash + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 /dev/sdb" + exit 1 +fi + +#!/bin/sh +# partitionne /dev/sdb en une partition unique FAT32 montable Win/Linux + +dev=$1 + +# créer table de partition MBR et 1 partition FAT32 +fdisk "$dev" < +-----BEGIN CERTIFICATE----- +MIIFnTCCA4WgAwIBAgIUCI574SM3Lyh47GyNl0WAOYrqb5QwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ0gxHzAdBgNVBAoMFlByb3RvbiBUZWNobm9sb2dpZXMg +QUcxEjAQBgNVBAsMCVByb3RvblZQTjEaMBgGA1UEAwwRUHJvdG9uVlBOIFJvb3Qg +Q0EwHhcNMTkxMDE3MDgwNjQxWhcNMzkxMDEyMDgwNjQxWjBeMQswCQYDVQQGEwJD +SDEfMB0GA1UECgwWUHJvdG9uIFRlY2hub2xvZ2llcyBBRzESMBAGA1UECwwJUHJv +dG9uVlBOMRowGAYDVQQDDBFQcm90b25WUE4gUm9vdCBDQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAMkUT7zMUS5C+NjQ7YoGpVFlfbN9HFgG4JiKfHB8 +QxnPPRgyTi0zVOAj1ImsRilauY8Ddm5dQtd8qcApoz6oCx5cFiiSQG2uyhS/59Zl +5wqIkw1o+CgwZgeWkq04lcrxhhfPgJZRFjrYVezy/Z2Ssd18s3/FFNQ+2iV1KC2K +z8eSPr50u+l9vEKsKiNGkJTdlWjoDKZM2C15i/h8Smi+PdJlx7WMTtYoVC1Fzq0r +aCPDQl18kspu11b6d8ECPWghKcDIIKuA0r0nGqF1GvH1AmbC/xUaNrKgz9AfioZL +MP/l22tVG3KKM1ku0eYHX7NzNHgkM2JKnBBannImQQBGTAcvvUlnfF3AHx4vzx7H +ahpBz8ebThx2uv+vzu8lCVEcKjQObGwLbAONJN2enug8hwSSZQv7tz7onDQWlYh0 +El5fnkrEQGbukNnSyOqTwfobvBllIPzBqdO38eZFA0YTlH9plYjIjPjGl931lFAA +3G9t0x7nxAauLXN5QVp1yoF1tzXc5kN0SFAasM9VtVEOSMaGHLKhF+IMyVX8h5Iu +IRC8u5O672r7cHS+Dtx87LjxypqNhmbf1TWyLJSoh0qYhMr+BbO7+N6zKRIZPI5b +MXc8Be2pQwbSA4ZrDvSjFC9yDXmSuZTyVo6Bqi/KCUZeaXKof68oNxVYeGowNeQd +g/znAgMBAAGjUzBRMB0GA1UdDgQWBBR44WtTuEKCaPPUltYEHZoyhJo+4TAfBgNV +HSMEGDAWgBR44WtTuEKCaPPUltYEHZoyhJo+4TAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQBBmzCQlHxOJ6izys3TVpaze+rUkA9GejgsB2DZXIcm +4Lj/SNzQsPlZRu4S0IZV253dbE1DoWlHanw5lnXwx8iU82X7jdm/5uZOwj2NqSqT +bTn0WLAC6khEKKe5bPTf18UOcwN82Le3AnkwcNAaBO5/TzFQVgnVedXr2g6rmpp9 +gdedeEl9acB7xqfYfkrmijqYMm+xeG2rXaanch3HjweMDuZdT/Ub5G6oir0Kowft +lA1ytjXRg+X+yWymTpF/zGLYfSodWWjMKhpzZtRJZ+9B0pWXUyY7SuCj5T5SMIAu +x3NQQ46wSbHRolIlwh7zD7kBgkyLe7ByLvGFKa2Vw4PuWjqYwrRbFjb2+EKAwPu6 +VTWz/QQTU8oJewGFipw94Bi61zuaPvF1qZCHgYhVojRy6KcqncX2Hx9hjfVxspBZ +DrVH6uofCmd99GmVu+qizybWQTrPaubfc/a2jJIbXc2bRQjYj/qmjE3hTlmO3k7V +EP6i8CLhEl+dX75aZw9StkqjdpIApYwX6XNDqVuGzfeTXXclk4N4aDPwPFM/Yo/e +KnvlNlKbljWdMYkfx8r37aOHpchH34cv0Jb5Im+1H07ywnshXNfUhRazOpubJRHn +bjDuBwWS1/Vwp5AJ+QHsPXhJdl3qHc1szJZVJb3VyAWvG/bWApKfFuZX18tiI4N0 +EA== +-----END CERTIFICATE----- + + + +-----BEGIN OpenVPN Static key V1----- +6acef03f62675b4b1bbd03e53b187727 +423cea742242106cb2916a8a4c829756 +3d22c7e5cef430b1103c6f66eb1fc5b3 +75a672f158e2e2e936c3faa48b035a6d +e17beaac23b5f03b10b868d53d03521d +8ba115059da777a60cbfd7b2c9c57472 +78a15b8f6e68a3ef7fd583ec9f398c8b +d4735dab40cbd1e3c62a822e97489186 +c30a0b48c7c38ea32ceb056d3fa5a710 +e10ccc7a0ddb363b08c3d2777a3395e1 +0c0b6080f56309192ab5aacd4b45f55d +a61fc77af39bd81a19218a79762c3386 +2df55785075f37d8c71dc8a42097ee43 +344739a0dd48d03025b0450cf1fb5e8c +aeb893d9a96d1f15519bb3c4dcb40ee3 +16672ea16c012664f8a9f11255518deb +-----END OpenVPN Static key V1----- + diff --git a/usr/etc/openvpn/client/ch-free-2.protonvpn.tcp.ovpn b/usr/etc/openvpn/client/ch-free-2.protonvpn.tcp.ovpn new file mode 100644 index 0000000..3e2ecef --- /dev/null +++ b/usr/etc/openvpn/client/ch-free-2.protonvpn.tcp.ovpn @@ -0,0 +1,123 @@ +# ============================================================================== +# Copyright (c) 2023 Proton AG (Switzerland) +# Email: contact@protonvpn.com +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ============================================================================== + +# The server you are connecting to is using a circuit in order to separate entry IP from exit IP +# The same entry IP allows to connect to multiple exit IPs in the same data center. + +# If you want to explicitly select the exit IP corresponding to server CH-FREE#2 you need to +# append a special suffix to your OpenVPN username. +# Please use "Gtd5u0nRC3vf1oRt+b:0" in order to enforce exiting through CH-FREE#2. + +# If you are a paying user you can also enable the ProtonVPN ad blocker (NetShield) or Moderate NAT: +# Use: "Gtd5u0nRC3vf1oRt+b:0+f1" to enable anti-malware filtering +# Use: "Gtd5u0nRC3vf1oRt+b:0+f2" to additionally enable ad-blocking filtering +# Use: "Gtd5u0nRC3vf1oRt+b:0+nr" to enable Moderate NAT +# Note that you can combine the "+nr" suffix with other suffixes. + +client +dev tun +proto tcp + +remote 138.199.6.177 7770 +remote 138.199.6.177 443 +remote 138.199.6.177 8443 + +remote-random +resolv-retry infinite +nobind + +cipher AES-256-GCM + +setenv CLIENT_CERT 0 +tun-mtu 1500 +mssfix 0 +persist-key +persist-tun + +reneg-sec 0 + +remote-cert-tls server +auth-user-pass + +script-security 2 +up /etc/openvpn/update-resolv-conf +down /etc/openvpn/update-resolv-conf + + +-----BEGIN CERTIFICATE----- +MIIFnTCCA4WgAwIBAgIUCI574SM3Lyh47GyNl0WAOYrqb5QwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ0gxHzAdBgNVBAoMFlByb3RvbiBUZWNobm9sb2dpZXMg +QUcxEjAQBgNVBAsMCVByb3RvblZQTjEaMBgGA1UEAwwRUHJvdG9uVlBOIFJvb3Qg +Q0EwHhcNMTkxMDE3MDgwNjQxWhcNMzkxMDEyMDgwNjQxWjBeMQswCQYDVQQGEwJD +SDEfMB0GA1UECgwWUHJvdG9uIFRlY2hub2xvZ2llcyBBRzESMBAGA1UECwwJUHJv +dG9uVlBOMRowGAYDVQQDDBFQcm90b25WUE4gUm9vdCBDQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAMkUT7zMUS5C+NjQ7YoGpVFlfbN9HFgG4JiKfHB8 +QxnPPRgyTi0zVOAj1ImsRilauY8Ddm5dQtd8qcApoz6oCx5cFiiSQG2uyhS/59Zl +5wqIkw1o+CgwZgeWkq04lcrxhhfPgJZRFjrYVezy/Z2Ssd18s3/FFNQ+2iV1KC2K +z8eSPr50u+l9vEKsKiNGkJTdlWjoDKZM2C15i/h8Smi+PdJlx7WMTtYoVC1Fzq0r +aCPDQl18kspu11b6d8ECPWghKcDIIKuA0r0nGqF1GvH1AmbC/xUaNrKgz9AfioZL +MP/l22tVG3KKM1ku0eYHX7NzNHgkM2JKnBBannImQQBGTAcvvUlnfF3AHx4vzx7H +ahpBz8ebThx2uv+vzu8lCVEcKjQObGwLbAONJN2enug8hwSSZQv7tz7onDQWlYh0 +El5fnkrEQGbukNnSyOqTwfobvBllIPzBqdO38eZFA0YTlH9plYjIjPjGl931lFAA +3G9t0x7nxAauLXN5QVp1yoF1tzXc5kN0SFAasM9VtVEOSMaGHLKhF+IMyVX8h5Iu +IRC8u5O672r7cHS+Dtx87LjxypqNhmbf1TWyLJSoh0qYhMr+BbO7+N6zKRIZPI5b +MXc8Be2pQwbSA4ZrDvSjFC9yDXmSuZTyVo6Bqi/KCUZeaXKof68oNxVYeGowNeQd +g/znAgMBAAGjUzBRMB0GA1UdDgQWBBR44WtTuEKCaPPUltYEHZoyhJo+4TAfBgNV +HSMEGDAWgBR44WtTuEKCaPPUltYEHZoyhJo+4TAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQBBmzCQlHxOJ6izys3TVpaze+rUkA9GejgsB2DZXIcm +4Lj/SNzQsPlZRu4S0IZV253dbE1DoWlHanw5lnXwx8iU82X7jdm/5uZOwj2NqSqT +bTn0WLAC6khEKKe5bPTf18UOcwN82Le3AnkwcNAaBO5/TzFQVgnVedXr2g6rmpp9 +gdedeEl9acB7xqfYfkrmijqYMm+xeG2rXaanch3HjweMDuZdT/Ub5G6oir0Kowft +lA1ytjXRg+X+yWymTpF/zGLYfSodWWjMKhpzZtRJZ+9B0pWXUyY7SuCj5T5SMIAu +x3NQQ46wSbHRolIlwh7zD7kBgkyLe7ByLvGFKa2Vw4PuWjqYwrRbFjb2+EKAwPu6 +VTWz/QQTU8oJewGFipw94Bi61zuaPvF1qZCHgYhVojRy6KcqncX2Hx9hjfVxspBZ +DrVH6uofCmd99GmVu+qizybWQTrPaubfc/a2jJIbXc2bRQjYj/qmjE3hTlmO3k7V +EP6i8CLhEl+dX75aZw9StkqjdpIApYwX6XNDqVuGzfeTXXclk4N4aDPwPFM/Yo/e +KnvlNlKbljWdMYkfx8r37aOHpchH34cv0Jb5Im+1H07ywnshXNfUhRazOpubJRHn +bjDuBwWS1/Vwp5AJ+QHsPXhJdl3qHc1szJZVJb3VyAWvG/bWApKfFuZX18tiI4N0 +EA== +-----END CERTIFICATE----- + + + +-----BEGIN OpenVPN Static key V1----- +6acef03f62675b4b1bbd03e53b187727 +423cea742242106cb2916a8a4c829756 +3d22c7e5cef430b1103c6f66eb1fc5b3 +75a672f158e2e2e936c3faa48b035a6d +e17beaac23b5f03b10b868d53d03521d +8ba115059da777a60cbfd7b2c9c57472 +78a15b8f6e68a3ef7fd583ec9f398c8b +d4735dab40cbd1e3c62a822e97489186 +c30a0b48c7c38ea32ceb056d3fa5a710 +e10ccc7a0ddb363b08c3d2777a3395e1 +0c0b6080f56309192ab5aacd4b45f55d +a61fc77af39bd81a19218a79762c3386 +2df55785075f37d8c71dc8a42097ee43 +344739a0dd48d03025b0450cf1fb5e8c +aeb893d9a96d1f15519bb3c4dcb40ee3 +16672ea16c012664f8a9f11255518deb +-----END OpenVPN Static key V1----- + diff --git a/usr/etc/openvpn/client/ch-free-6.protonvpn.tcp.ovpn b/usr/etc/openvpn/client/ch-free-6.protonvpn.tcp.ovpn new file mode 100644 index 0000000..60eb9ca --- /dev/null +++ b/usr/etc/openvpn/client/ch-free-6.protonvpn.tcp.ovpn @@ -0,0 +1,123 @@ +# ============================================================================== +# Copyright (c) 2023 Proton AG (Switzerland) +# Email: contact@protonvpn.com +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ============================================================================== + +# The server you are connecting to is using a circuit in order to separate entry IP from exit IP +# The same entry IP allows to connect to multiple exit IPs in the same data center. + +# If you want to explicitly select the exit IP corresponding to server CH-FREE#6 you need to +# append a special suffix to your OpenVPN username. +# Please use "Gtd5u0nRC3vf1oRt+b:0" in order to enforce exiting through CH-FREE#6. + +# If you are a paying user you can also enable the ProtonVPN ad blocker (NetShield) or Moderate NAT: +# Use: "Gtd5u0nRC3vf1oRt+b:0+f1" to enable anti-malware filtering +# Use: "Gtd5u0nRC3vf1oRt+b:0+f2" to additionally enable ad-blocking filtering +# Use: "Gtd5u0nRC3vf1oRt+b:0+nr" to enable Moderate NAT +# Note that you can combine the "+nr" suffix with other suffixes. + +client +dev tun +proto tcp + +remote 149.88.27.232 7770 +remote 149.88.27.232 8443 +remote 149.88.27.232 443 + +remote-random +resolv-retry infinite +nobind + +cipher AES-256-GCM + +setenv CLIENT_CERT 0 +tun-mtu 1500 +mssfix 0 +persist-key +persist-tun + +reneg-sec 0 + +remote-cert-tls server +auth-user-pass + +script-security 2 +up /etc/openvpn/update-resolv-conf +down /etc/openvpn/update-resolv-conf + + +-----BEGIN CERTIFICATE----- +MIIFnTCCA4WgAwIBAgIUCI574SM3Lyh47GyNl0WAOYrqb5QwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ0gxHzAdBgNVBAoMFlByb3RvbiBUZWNobm9sb2dpZXMg +QUcxEjAQBgNVBAsMCVByb3RvblZQTjEaMBgGA1UEAwwRUHJvdG9uVlBOIFJvb3Qg +Q0EwHhcNMTkxMDE3MDgwNjQxWhcNMzkxMDEyMDgwNjQxWjBeMQswCQYDVQQGEwJD +SDEfMB0GA1UECgwWUHJvdG9uIFRlY2hub2xvZ2llcyBBRzESMBAGA1UECwwJUHJv +dG9uVlBOMRowGAYDVQQDDBFQcm90b25WUE4gUm9vdCBDQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAMkUT7zMUS5C+NjQ7YoGpVFlfbN9HFgG4JiKfHB8 +QxnPPRgyTi0zVOAj1ImsRilauY8Ddm5dQtd8qcApoz6oCx5cFiiSQG2uyhS/59Zl +5wqIkw1o+CgwZgeWkq04lcrxhhfPgJZRFjrYVezy/Z2Ssd18s3/FFNQ+2iV1KC2K +z8eSPr50u+l9vEKsKiNGkJTdlWjoDKZM2C15i/h8Smi+PdJlx7WMTtYoVC1Fzq0r +aCPDQl18kspu11b6d8ECPWghKcDIIKuA0r0nGqF1GvH1AmbC/xUaNrKgz9AfioZL +MP/l22tVG3KKM1ku0eYHX7NzNHgkM2JKnBBannImQQBGTAcvvUlnfF3AHx4vzx7H +ahpBz8ebThx2uv+vzu8lCVEcKjQObGwLbAONJN2enug8hwSSZQv7tz7onDQWlYh0 +El5fnkrEQGbukNnSyOqTwfobvBllIPzBqdO38eZFA0YTlH9plYjIjPjGl931lFAA +3G9t0x7nxAauLXN5QVp1yoF1tzXc5kN0SFAasM9VtVEOSMaGHLKhF+IMyVX8h5Iu +IRC8u5O672r7cHS+Dtx87LjxypqNhmbf1TWyLJSoh0qYhMr+BbO7+N6zKRIZPI5b +MXc8Be2pQwbSA4ZrDvSjFC9yDXmSuZTyVo6Bqi/KCUZeaXKof68oNxVYeGowNeQd +g/znAgMBAAGjUzBRMB0GA1UdDgQWBBR44WtTuEKCaPPUltYEHZoyhJo+4TAfBgNV +HSMEGDAWgBR44WtTuEKCaPPUltYEHZoyhJo+4TAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQBBmzCQlHxOJ6izys3TVpaze+rUkA9GejgsB2DZXIcm +4Lj/SNzQsPlZRu4S0IZV253dbE1DoWlHanw5lnXwx8iU82X7jdm/5uZOwj2NqSqT +bTn0WLAC6khEKKe5bPTf18UOcwN82Le3AnkwcNAaBO5/TzFQVgnVedXr2g6rmpp9 +gdedeEl9acB7xqfYfkrmijqYMm+xeG2rXaanch3HjweMDuZdT/Ub5G6oir0Kowft +lA1ytjXRg+X+yWymTpF/zGLYfSodWWjMKhpzZtRJZ+9B0pWXUyY7SuCj5T5SMIAu +x3NQQ46wSbHRolIlwh7zD7kBgkyLe7ByLvGFKa2Vw4PuWjqYwrRbFjb2+EKAwPu6 +VTWz/QQTU8oJewGFipw94Bi61zuaPvF1qZCHgYhVojRy6KcqncX2Hx9hjfVxspBZ +DrVH6uofCmd99GmVu+qizybWQTrPaubfc/a2jJIbXc2bRQjYj/qmjE3hTlmO3k7V +EP6i8CLhEl+dX75aZw9StkqjdpIApYwX6XNDqVuGzfeTXXclk4N4aDPwPFM/Yo/e +KnvlNlKbljWdMYkfx8r37aOHpchH34cv0Jb5Im+1H07ywnshXNfUhRazOpubJRHn +bjDuBwWS1/Vwp5AJ+QHsPXhJdl3qHc1szJZVJb3VyAWvG/bWApKfFuZX18tiI4N0 +EA== +-----END CERTIFICATE----- + + + +-----BEGIN OpenVPN Static key V1----- +6acef03f62675b4b1bbd03e53b187727 +423cea742242106cb2916a8a4c829756 +3d22c7e5cef430b1103c6f66eb1fc5b3 +75a672f158e2e2e936c3faa48b035a6d +e17beaac23b5f03b10b868d53d03521d +8ba115059da777a60cbfd7b2c9c57472 +78a15b8f6e68a3ef7fd583ec9f398c8b +d4735dab40cbd1e3c62a822e97489186 +c30a0b48c7c38ea32ceb056d3fa5a710 +e10ccc7a0ddb363b08c3d2777a3395e1 +0c0b6080f56309192ab5aacd4b45f55d +a61fc77af39bd81a19218a79762c3386 +2df55785075f37d8c71dc8a42097ee43 +344739a0dd48d03025b0450cf1fb5e8c +aeb893d9a96d1f15519bb3c4dcb40ee3 +16672ea16c012664f8a9f11255518deb +-----END OpenVPN Static key V1----- + diff --git a/usr/etc/openvpn/client/client.conf b/usr/etc/openvpn/client/client.conf new file mode 100644 index 0000000..cf9c4b3 --- /dev/null +++ b/usr/etc/openvpn/client/client.conf @@ -0,0 +1,10 @@ +client +remote example.com 1194 udp + +script-security 2 +setenv PATH /usr/bin +up /etc/openvpn/scripts/update-systemd-resolved +down /etc/openvpn/scripts/update-systemd-resolved +down-pre + +dhcp-option DOMAIN-ROUTE . diff --git a/usr/etc/openvpn/client/jp-free-33.protonvpn.tcp.ovpn b/usr/etc/openvpn/client/jp-free-33.protonvpn.tcp.ovpn new file mode 100644 index 0000000..7530da0 --- /dev/null +++ b/usr/etc/openvpn/client/jp-free-33.protonvpn.tcp.ovpn @@ -0,0 +1,123 @@ +# ============================================================================== +# Copyright (c) 2023 Proton AG (Switzerland) +# Email: contact@protonvpn.com +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ============================================================================== + +# The server you are connecting to is using a circuit in order to separate entry IP from exit IP +# The same entry IP allows to connect to multiple exit IPs in the same data center. + +# If you want to explicitly select the exit IP corresponding to server JP-FREE#33 you need to +# append a special suffix to your OpenVPN username. +# Please use "Gtd5u0nRC3vf1oRt+b:0" in order to enforce exiting through JP-FREE#33. + +# If you are a paying user you can also enable the ProtonVPN ad blocker (NetShield) or Moderate NAT: +# Use: "Gtd5u0nRC3vf1oRt+b:0+f1" to enable anti-malware filtering +# Use: "Gtd5u0nRC3vf1oRt+b:0+f2" to additionally enable ad-blocking filtering +# Use: "Gtd5u0nRC3vf1oRt+b:0+nr" to enable Moderate NAT +# Note that you can combine the "+nr" suffix with other suffixes. + +client +dev tun +proto tcp + +remote 149.88.103.161 7770 +remote 149.88.103.161 8443 +remote 149.88.103.161 443 + +remote-random +resolv-retry infinite +nobind + +cipher AES-256-GCM + +setenv CLIENT_CERT 0 +tun-mtu 1500 +mssfix 0 +persist-key +persist-tun + +reneg-sec 0 + +remote-cert-tls server +auth-user-pass + +script-security 2 +up /etc/openvpn/update-resolv-conf +down /etc/openvpn/update-resolv-conf + + +-----BEGIN CERTIFICATE----- +MIIFnTCCA4WgAwIBAgIUCI574SM3Lyh47GyNl0WAOYrqb5QwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ0gxHzAdBgNVBAoMFlByb3RvbiBUZWNobm9sb2dpZXMg +QUcxEjAQBgNVBAsMCVByb3RvblZQTjEaMBgGA1UEAwwRUHJvdG9uVlBOIFJvb3Qg +Q0EwHhcNMTkxMDE3MDgwNjQxWhcNMzkxMDEyMDgwNjQxWjBeMQswCQYDVQQGEwJD +SDEfMB0GA1UECgwWUHJvdG9uIFRlY2hub2xvZ2llcyBBRzESMBAGA1UECwwJUHJv +dG9uVlBOMRowGAYDVQQDDBFQcm90b25WUE4gUm9vdCBDQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAMkUT7zMUS5C+NjQ7YoGpVFlfbN9HFgG4JiKfHB8 +QxnPPRgyTi0zVOAj1ImsRilauY8Ddm5dQtd8qcApoz6oCx5cFiiSQG2uyhS/59Zl +5wqIkw1o+CgwZgeWkq04lcrxhhfPgJZRFjrYVezy/Z2Ssd18s3/FFNQ+2iV1KC2K +z8eSPr50u+l9vEKsKiNGkJTdlWjoDKZM2C15i/h8Smi+PdJlx7WMTtYoVC1Fzq0r +aCPDQl18kspu11b6d8ECPWghKcDIIKuA0r0nGqF1GvH1AmbC/xUaNrKgz9AfioZL +MP/l22tVG3KKM1ku0eYHX7NzNHgkM2JKnBBannImQQBGTAcvvUlnfF3AHx4vzx7H +ahpBz8ebThx2uv+vzu8lCVEcKjQObGwLbAONJN2enug8hwSSZQv7tz7onDQWlYh0 +El5fnkrEQGbukNnSyOqTwfobvBllIPzBqdO38eZFA0YTlH9plYjIjPjGl931lFAA +3G9t0x7nxAauLXN5QVp1yoF1tzXc5kN0SFAasM9VtVEOSMaGHLKhF+IMyVX8h5Iu +IRC8u5O672r7cHS+Dtx87LjxypqNhmbf1TWyLJSoh0qYhMr+BbO7+N6zKRIZPI5b +MXc8Be2pQwbSA4ZrDvSjFC9yDXmSuZTyVo6Bqi/KCUZeaXKof68oNxVYeGowNeQd +g/znAgMBAAGjUzBRMB0GA1UdDgQWBBR44WtTuEKCaPPUltYEHZoyhJo+4TAfBgNV +HSMEGDAWgBR44WtTuEKCaPPUltYEHZoyhJo+4TAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQBBmzCQlHxOJ6izys3TVpaze+rUkA9GejgsB2DZXIcm +4Lj/SNzQsPlZRu4S0IZV253dbE1DoWlHanw5lnXwx8iU82X7jdm/5uZOwj2NqSqT +bTn0WLAC6khEKKe5bPTf18UOcwN82Le3AnkwcNAaBO5/TzFQVgnVedXr2g6rmpp9 +gdedeEl9acB7xqfYfkrmijqYMm+xeG2rXaanch3HjweMDuZdT/Ub5G6oir0Kowft +lA1ytjXRg+X+yWymTpF/zGLYfSodWWjMKhpzZtRJZ+9B0pWXUyY7SuCj5T5SMIAu +x3NQQ46wSbHRolIlwh7zD7kBgkyLe7ByLvGFKa2Vw4PuWjqYwrRbFjb2+EKAwPu6 +VTWz/QQTU8oJewGFipw94Bi61zuaPvF1qZCHgYhVojRy6KcqncX2Hx9hjfVxspBZ +DrVH6uofCmd99GmVu+qizybWQTrPaubfc/a2jJIbXc2bRQjYj/qmjE3hTlmO3k7V +EP6i8CLhEl+dX75aZw9StkqjdpIApYwX6XNDqVuGzfeTXXclk4N4aDPwPFM/Yo/e +KnvlNlKbljWdMYkfx8r37aOHpchH34cv0Jb5Im+1H07ywnshXNfUhRazOpubJRHn +bjDuBwWS1/Vwp5AJ+QHsPXhJdl3qHc1szJZVJb3VyAWvG/bWApKfFuZX18tiI4N0 +EA== +-----END CERTIFICATE----- + + + +-----BEGIN OpenVPN Static key V1----- +6acef03f62675b4b1bbd03e53b187727 +423cea742242106cb2916a8a4c829756 +3d22c7e5cef430b1103c6f66eb1fc5b3 +75a672f158e2e2e936c3faa48b035a6d +e17beaac23b5f03b10b868d53d03521d +8ba115059da777a60cbfd7b2c9c57472 +78a15b8f6e68a3ef7fd583ec9f398c8b +d4735dab40cbd1e3c62a822e97489186 +c30a0b48c7c38ea32ceb056d3fa5a710 +e10ccc7a0ddb363b08c3d2777a3395e1 +0c0b6080f56309192ab5aacd4b45f55d +a61fc77af39bd81a19218a79762c3386 +2df55785075f37d8c71dc8a42097ee43 +344739a0dd48d03025b0450cf1fb5e8c +aeb893d9a96d1f15519bb3c4dcb40ee3 +16672ea16c012664f8a9f11255518deb +-----END OpenVPN Static key V1----- + diff --git a/usr/etc/openvpn/client/no-free-4.protonvpn.tcp.ovpn b/usr/etc/openvpn/client/no-free-4.protonvpn.tcp.ovpn new file mode 100644 index 0000000..28a420f --- /dev/null +++ b/usr/etc/openvpn/client/no-free-4.protonvpn.tcp.ovpn @@ -0,0 +1,123 @@ +# ============================================================================== +# Copyright (c) 2023 Proton AG (Switzerland) +# Email: contact@protonvpn.com +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ============================================================================== + +# The server you are connecting to is using a circuit in order to separate entry IP from exit IP +# The same entry IP allows to connect to multiple exit IPs in the same data center. + +# If you want to explicitly select the exit IP corresponding to server NO-FREE#4 you need to +# append a special suffix to your OpenVPN username. +# Please use "Gtd5u0nRC3vf1oRt+b:0" in order to enforce exiting through NO-FREE#4. + +# If you are a paying user you can also enable the ProtonVPN ad blocker (NetShield) or Moderate NAT: +# Use: "Gtd5u0nRC3vf1oRt+b:0+f1" to enable anti-malware filtering +# Use: "Gtd5u0nRC3vf1oRt+b:0+f2" to additionally enable ad-blocking filtering +# Use: "Gtd5u0nRC3vf1oRt+b:0+nr" to enable Moderate NAT +# Note that you can combine the "+nr" suffix with other suffixes. + +client +dev tun +proto tcp + +remote 95.173.205.164 8443 +remote 95.173.205.164 7770 +remote 95.173.205.164 443 + +remote-random +resolv-retry infinite +nobind + +cipher AES-256-GCM + +setenv CLIENT_CERT 0 +tun-mtu 1500 +mssfix 0 +persist-key +persist-tun + +reneg-sec 0 + +remote-cert-tls server +auth-user-pass + +script-security 2 +up /etc/openvpn/update-resolv-conf +down /etc/openvpn/update-resolv-conf + + +-----BEGIN CERTIFICATE----- +MIIFnTCCA4WgAwIBAgIUCI574SM3Lyh47GyNl0WAOYrqb5QwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ0gxHzAdBgNVBAoMFlByb3RvbiBUZWNobm9sb2dpZXMg +QUcxEjAQBgNVBAsMCVByb3RvblZQTjEaMBgGA1UEAwwRUHJvdG9uVlBOIFJvb3Qg +Q0EwHhcNMTkxMDE3MDgwNjQxWhcNMzkxMDEyMDgwNjQxWjBeMQswCQYDVQQGEwJD +SDEfMB0GA1UECgwWUHJvdG9uIFRlY2hub2xvZ2llcyBBRzESMBAGA1UECwwJUHJv +dG9uVlBOMRowGAYDVQQDDBFQcm90b25WUE4gUm9vdCBDQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAMkUT7zMUS5C+NjQ7YoGpVFlfbN9HFgG4JiKfHB8 +QxnPPRgyTi0zVOAj1ImsRilauY8Ddm5dQtd8qcApoz6oCx5cFiiSQG2uyhS/59Zl +5wqIkw1o+CgwZgeWkq04lcrxhhfPgJZRFjrYVezy/Z2Ssd18s3/FFNQ+2iV1KC2K +z8eSPr50u+l9vEKsKiNGkJTdlWjoDKZM2C15i/h8Smi+PdJlx7WMTtYoVC1Fzq0r +aCPDQl18kspu11b6d8ECPWghKcDIIKuA0r0nGqF1GvH1AmbC/xUaNrKgz9AfioZL +MP/l22tVG3KKM1ku0eYHX7NzNHgkM2JKnBBannImQQBGTAcvvUlnfF3AHx4vzx7H +ahpBz8ebThx2uv+vzu8lCVEcKjQObGwLbAONJN2enug8hwSSZQv7tz7onDQWlYh0 +El5fnkrEQGbukNnSyOqTwfobvBllIPzBqdO38eZFA0YTlH9plYjIjPjGl931lFAA +3G9t0x7nxAauLXN5QVp1yoF1tzXc5kN0SFAasM9VtVEOSMaGHLKhF+IMyVX8h5Iu +IRC8u5O672r7cHS+Dtx87LjxypqNhmbf1TWyLJSoh0qYhMr+BbO7+N6zKRIZPI5b +MXc8Be2pQwbSA4ZrDvSjFC9yDXmSuZTyVo6Bqi/KCUZeaXKof68oNxVYeGowNeQd +g/znAgMBAAGjUzBRMB0GA1UdDgQWBBR44WtTuEKCaPPUltYEHZoyhJo+4TAfBgNV +HSMEGDAWgBR44WtTuEKCaPPUltYEHZoyhJo+4TAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQBBmzCQlHxOJ6izys3TVpaze+rUkA9GejgsB2DZXIcm +4Lj/SNzQsPlZRu4S0IZV253dbE1DoWlHanw5lnXwx8iU82X7jdm/5uZOwj2NqSqT +bTn0WLAC6khEKKe5bPTf18UOcwN82Le3AnkwcNAaBO5/TzFQVgnVedXr2g6rmpp9 +gdedeEl9acB7xqfYfkrmijqYMm+xeG2rXaanch3HjweMDuZdT/Ub5G6oir0Kowft +lA1ytjXRg+X+yWymTpF/zGLYfSodWWjMKhpzZtRJZ+9B0pWXUyY7SuCj5T5SMIAu +x3NQQ46wSbHRolIlwh7zD7kBgkyLe7ByLvGFKa2Vw4PuWjqYwrRbFjb2+EKAwPu6 +VTWz/QQTU8oJewGFipw94Bi61zuaPvF1qZCHgYhVojRy6KcqncX2Hx9hjfVxspBZ +DrVH6uofCmd99GmVu+qizybWQTrPaubfc/a2jJIbXc2bRQjYj/qmjE3hTlmO3k7V +EP6i8CLhEl+dX75aZw9StkqjdpIApYwX6XNDqVuGzfeTXXclk4N4aDPwPFM/Yo/e +KnvlNlKbljWdMYkfx8r37aOHpchH34cv0Jb5Im+1H07ywnshXNfUhRazOpubJRHn +bjDuBwWS1/Vwp5AJ+QHsPXhJdl3qHc1szJZVJb3VyAWvG/bWApKfFuZX18tiI4N0 +EA== +-----END CERTIFICATE----- + + + +-----BEGIN OpenVPN Static key V1----- +6acef03f62675b4b1bbd03e53b187727 +423cea742242106cb2916a8a4c829756 +3d22c7e5cef430b1103c6f66eb1fc5b3 +75a672f158e2e2e936c3faa48b035a6d +e17beaac23b5f03b10b868d53d03521d +8ba115059da777a60cbfd7b2c9c57472 +78a15b8f6e68a3ef7fd583ec9f398c8b +d4735dab40cbd1e3c62a822e97489186 +c30a0b48c7c38ea32ceb056d3fa5a710 +e10ccc7a0ddb363b08c3d2777a3395e1 +0c0b6080f56309192ab5aacd4b45f55d +a61fc77af39bd81a19218a79762c3386 +2df55785075f37d8c71dc8a42097ee43 +344739a0dd48d03025b0450cf1fb5e8c +aeb893d9a96d1f15519bb3c4dcb40ee3 +16672ea16c012664f8a9f11255518deb +-----END OpenVPN Static key V1----- + diff --git a/usr/etc/openvpn/client/us-free-74.protonvpn.tcp.ovpn b/usr/etc/openvpn/client/us-free-74.protonvpn.tcp.ovpn new file mode 100644 index 0000000..1f45b40 --- /dev/null +++ b/usr/etc/openvpn/client/us-free-74.protonvpn.tcp.ovpn @@ -0,0 +1,123 @@ +# ============================================================================== +# Copyright (c) 2023 Proton AG (Switzerland) +# Email: contact@protonvpn.com +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# ============================================================================== + +# The server you are connecting to is using a circuit in order to separate entry IP from exit IP +# The same entry IP allows to connect to multiple exit IPs in the same data center. + +# If you want to explicitly select the exit IP corresponding to server US-FREE#74 you need to +# append a special suffix to your OpenVPN username. +# Please use "Gtd5u0nRC3vf1oRt+b:0" in order to enforce exiting through US-FREE#74. + +# If you are a paying user you can also enable the ProtonVPN ad blocker (NetShield) or Moderate NAT: +# Use: "Gtd5u0nRC3vf1oRt+b:0+f1" to enable anti-malware filtering +# Use: "Gtd5u0nRC3vf1oRt+b:0+f2" to additionally enable ad-blocking filtering +# Use: "Gtd5u0nRC3vf1oRt+b:0+nr" to enable Moderate NAT +# Note that you can combine the "+nr" suffix with other suffixes. + +client +dev tun +proto tcp + +remote 151.243.141.162 443 +remote 151.243.141.162 8443 +remote 151.243.141.162 7770 + +remote-random +resolv-retry infinite +nobind + +cipher AES-256-GCM + +setenv CLIENT_CERT 0 +tun-mtu 1500 +mssfix 0 +persist-key +persist-tun + +reneg-sec 0 + +remote-cert-tls server +auth-user-pass + +script-security 2 +up /etc/openvpn/update-resolv-conf +down /etc/openvpn/update-resolv-conf + + +-----BEGIN CERTIFICATE----- +MIIFnTCCA4WgAwIBAgIUCI574SM3Lyh47GyNl0WAOYrqb5QwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ0gxHzAdBgNVBAoMFlByb3RvbiBUZWNobm9sb2dpZXMg +QUcxEjAQBgNVBAsMCVByb3RvblZQTjEaMBgGA1UEAwwRUHJvdG9uVlBOIFJvb3Qg +Q0EwHhcNMTkxMDE3MDgwNjQxWhcNMzkxMDEyMDgwNjQxWjBeMQswCQYDVQQGEwJD +SDEfMB0GA1UECgwWUHJvdG9uIFRlY2hub2xvZ2llcyBBRzESMBAGA1UECwwJUHJv +dG9uVlBOMRowGAYDVQQDDBFQcm90b25WUE4gUm9vdCBDQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAMkUT7zMUS5C+NjQ7YoGpVFlfbN9HFgG4JiKfHB8 +QxnPPRgyTi0zVOAj1ImsRilauY8Ddm5dQtd8qcApoz6oCx5cFiiSQG2uyhS/59Zl +5wqIkw1o+CgwZgeWkq04lcrxhhfPgJZRFjrYVezy/Z2Ssd18s3/FFNQ+2iV1KC2K +z8eSPr50u+l9vEKsKiNGkJTdlWjoDKZM2C15i/h8Smi+PdJlx7WMTtYoVC1Fzq0r +aCPDQl18kspu11b6d8ECPWghKcDIIKuA0r0nGqF1GvH1AmbC/xUaNrKgz9AfioZL +MP/l22tVG3KKM1ku0eYHX7NzNHgkM2JKnBBannImQQBGTAcvvUlnfF3AHx4vzx7H +ahpBz8ebThx2uv+vzu8lCVEcKjQObGwLbAONJN2enug8hwSSZQv7tz7onDQWlYh0 +El5fnkrEQGbukNnSyOqTwfobvBllIPzBqdO38eZFA0YTlH9plYjIjPjGl931lFAA +3G9t0x7nxAauLXN5QVp1yoF1tzXc5kN0SFAasM9VtVEOSMaGHLKhF+IMyVX8h5Iu +IRC8u5O672r7cHS+Dtx87LjxypqNhmbf1TWyLJSoh0qYhMr+BbO7+N6zKRIZPI5b +MXc8Be2pQwbSA4ZrDvSjFC9yDXmSuZTyVo6Bqi/KCUZeaXKof68oNxVYeGowNeQd +g/znAgMBAAGjUzBRMB0GA1UdDgQWBBR44WtTuEKCaPPUltYEHZoyhJo+4TAfBgNV +HSMEGDAWgBR44WtTuEKCaPPUltYEHZoyhJo+4TAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQBBmzCQlHxOJ6izys3TVpaze+rUkA9GejgsB2DZXIcm +4Lj/SNzQsPlZRu4S0IZV253dbE1DoWlHanw5lnXwx8iU82X7jdm/5uZOwj2NqSqT +bTn0WLAC6khEKKe5bPTf18UOcwN82Le3AnkwcNAaBO5/TzFQVgnVedXr2g6rmpp9 +gdedeEl9acB7xqfYfkrmijqYMm+xeG2rXaanch3HjweMDuZdT/Ub5G6oir0Kowft +lA1ytjXRg+X+yWymTpF/zGLYfSodWWjMKhpzZtRJZ+9B0pWXUyY7SuCj5T5SMIAu +x3NQQ46wSbHRolIlwh7zD7kBgkyLe7ByLvGFKa2Vw4PuWjqYwrRbFjb2+EKAwPu6 +VTWz/QQTU8oJewGFipw94Bi61zuaPvF1qZCHgYhVojRy6KcqncX2Hx9hjfVxspBZ +DrVH6uofCmd99GmVu+qizybWQTrPaubfc/a2jJIbXc2bRQjYj/qmjE3hTlmO3k7V +EP6i8CLhEl+dX75aZw9StkqjdpIApYwX6XNDqVuGzfeTXXclk4N4aDPwPFM/Yo/e +KnvlNlKbljWdMYkfx8r37aOHpchH34cv0Jb5Im+1H07ywnshXNfUhRazOpubJRHn +bjDuBwWS1/Vwp5AJ+QHsPXhJdl3qHc1szJZVJb3VyAWvG/bWApKfFuZX18tiI4N0 +EA== +-----END CERTIFICATE----- + + + +-----BEGIN OpenVPN Static key V1----- +6acef03f62675b4b1bbd03e53b187727 +423cea742242106cb2916a8a4c829756 +3d22c7e5cef430b1103c6f66eb1fc5b3 +75a672f158e2e2e936c3faa48b035a6d +e17beaac23b5f03b10b868d53d03521d +8ba115059da777a60cbfd7b2c9c57472 +78a15b8f6e68a3ef7fd583ec9f398c8b +d4735dab40cbd1e3c62a822e97489186 +c30a0b48c7c38ea32ceb056d3fa5a710 +e10ccc7a0ddb363b08c3d2777a3395e1 +0c0b6080f56309192ab5aacd4b45f55d +a61fc77af39bd81a19218a79762c3386 +2df55785075f37d8c71dc8a42097ee43 +344739a0dd48d03025b0450cf1fb5e8c +aeb893d9a96d1f15519bb3c4dcb40ee3 +16672ea16c012664f8a9f11255518deb +-----END OpenVPN Static key V1----- + diff --git a/usr/etc/openvpn/scripts/update-systemd-resolved b/usr/etc/openvpn/scripts/update-systemd-resolved new file mode 100644 index 0000000..a4a7d20 --- /dev/null +++ b/usr/etc/openvpn/scripts/update-systemd-resolved @@ -0,0 +1,1524 @@ +#!/usr/bin/env bash +# +# OpenVPN helper to add DHCP information into systemd-resolved via DBus. +# Copyright (C) 2016, Jonathan Wright +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This script will parse DHCP options set via OpenVPN (dhcp-option) to update +# systemd-resolved directly via DBus, instead of updating /etc/resolv.conf. To +# install, set as the 'up' and 'down' script in your OpenVPN configuration file +# or via the command-line arguments, alongside setting the 'down-pre' option to +# run the 'down' script before the device is closed. For example: +# +# script-security 2 +# up /usr/local/libexec/openvpn/update-systemd-resolved +# up-restart +# down /usr/local/libexec/openvpn/update-systemd-resolved +# down-pre + +# Define what needs to be called via DBus +DBUS_DEST="org.freedesktop.resolve1" +DBUS_NODE="/org/freedesktop/resolve1" + +SCRIPT_NAME="${BASH_SOURCE[0]##*/}" + +if [[ -S /dev/log ]] && command -v logger &> /dev/null; then + if [[ -t 2 ]]; then + log() { + logger -s -t "$SCRIPT_NAME" "$@" + } + else + # Suppress output on stderr when not attached to a (p|t)ty. + # https://github.com/jonathanio/update-systemd-resolved/issues/81 + log() { + logger -t "$SCRIPT_NAME" "$@" + } + fi + + for level in err warning info debug; do + printf -v functext -- '%s() { log -p user.%s -- "$@" ; }' "$level" "$level" + eval "$functext" + done +else + log() { + printf 1>&2 -- '%s: %s\n' "$SCRIPT_NAME" "$*" + } + + for level in err warning info debug; do + printf -v functext -- '%s() { log "%s:" "$@" ; }' "$level" "${level^^}" + eval "$functext" + done +fi + +usage() { + err "${1:?${1}. }. Usage: ${SCRIPT_NAME} up|down|print-polkit-rules []." +} + +busctl_status() { + busctl status "$DBUS_DEST" +} + +busctl_call() { + # Preserve busctl's exit status + busctl call "$DBUS_DEST" "$DBUS_NODE" "${DBUS_DEST}.Manager" "$@" || { + local -i status=$? + err "'busctl' exited with status $status" + print_polkit_rules_command_for_current_user | err + return $status + } +} + +get_link_info() { + dev="$1" + shift + + link='' + link="$(ip link show dev "$dev")" || return $? + + echo "$dev" "${link%%:*}" +} + +each_dhcp_setting() { + local foreign_option foreign_option_value setting_type setting_value + + for foreign_option in "${!foreign_option_@}"; do + foreign_option_value="${!foreign_option}" + + # Matches: + # + # dhcp-option SOME-SETTING a-value + # dhcp-option ANOTHER-SETTING + # + # In the second case, the setting value is the empty string. + if [[ $foreign_option_value =~ ^[[:space:]]*dhcp-option[[:space:]]+([^[:space:]]+)([[:space:]]+(.*))?$ ]]; then + "$@" "${BASH_REMATCH[1]}" "${BASH_REMATCH[3]-}" || return + fi + done +} + +# Check that a function was supplied the expected number of arguments. If not, +# issue a diagnostic message and return nonzero status. +usage_for() { + if [[ ${FUNCNAME[1]} != "${FUNCNAME[0]}" ]]; then + usage_for 4 - "$#" ' [ ...]' || return + fi + + local caller="${FUNCNAME[1]}" + + local -i argc_min + + case "$1" in + -) + argc_min=0 + ;; + *) + argc_min="$1" + ;; + esac + + shift + + local have_argc_max + local -i argc_max + + case "$1" in + -) ;; + *) + have_argc_max=yes + argc_max="$1" + ;; + esac + + shift + + local -i argc="$1" + shift + + if ((argc < argc_min)) || { [[ -n ${have_argc_max-} ]] && ((argc > argc_max)); }; then + local expectation + if [[ -n ${have_argc_max-} ]]; then + if ((argc_min == argc_max)); then + expectation="exactly ${argc_min}" + else + expectation="from ${argc_min} to ${argc_max}" + fi + else + expectation="at least ${argc_min}" + fi + + err "${caller}: got ${argc} argument(s); expected ${expectation}" + err "usage: ${caller} $*" + + return 64 # EX_USAGE + fi +} + +# mapfile wrapper that (unlike "mapfile -t somevar < <(some command)") bubbles +# up the exit status of the command used to generate the output read into the +# mapfile'd variable. +mapfile_from_command() { + usage_for 2 - "$#" ' [ ...]' || return + + local -a passthru + + while (("$#" > 0)); do + case "$1" in + -d | -n | -O | -s | -u | -C | -c) + passthru+=("$1" "$2") + shift + ;; + -t) + passthru+=("$1") + ;; + --) + shift + break + ;; + *) + break + ;; + esac + + shift + done + + var="$1" + shift + + local out + out="$("$@")" || return + + # "printf" rather than herestring ("<<<"); avoids introducing a newline + mapfile "${passthru[@]}" "$var" < <(printf -- '%s' "$out") +} + +# Work around this: +# +# $ IFS=$'.' read -r -a octets <<<192.168.1.1. # note trailing "." +# $ echo "${#octets[@]}" +# 4 +# $ echo "${octets[-1]}" +# 1 +# $ mapfile -d $'.' -t octets < <(printf -- '192.168.2.1.') +# $ echo "${#octets[@]}" +# 4 +# $ echo "${octets[-1]}" +# 1 +# +# This function is like "read -r -a" or "mapfile -t", except that it adds an +# empty string in the final spot in the generated array if the source string +# ends with the separator sequence. +# +# NOTE: uses "declare -n", so requires Bash >= 4.3 +split_on_separator_into() { + usage_for 3 3 "$#" ' ' || return + + local sep="$1" + shift + + local -n rvar="$1" + shift + + # "printf" rather than herestring ("<<<"); avoids introducing a newline. + # Cannot count on "mapfile -d", which was released in the relatively-recent + # Bash 5.0, so use a workaround that handles only a single line of input. + IFS="$sep" read -r -a rvar < <(printf -- '%s' "$1") || : + + if [[ $1 == *"$sep" ]]; then + rvar+=('') + fi +} + +# Print the supplied arguments as a string joined with the specified separator +print_with_separator() { + usage_for 1 - "$#" ' [ ...]' || return + + local sep="$1" + shift + + printf -- '%s' "$1" + shift + + if (("$#" < 1)); then + return + fi + + printf -- "${sep}%s" "$@" +} + +# Like "print_with_separator", but adds a final newline +puts_with_separator() { + usage_for 1 - "$#" ' [ ...]' || return + print_with_separator "$@" || return + printf -- '\n' +} + +with_openvpn_script_handling() { + if (("$#" == 0)); then + usage 'No script type specified' + return 1 + fi + + local func="$1" + shift || : + + local dev="${1:-${dev-}}" + shift || : + + if [[ -z ${dev-} ]]; then + usage 'No device name specified' + return 1 + fi + + if ! read -r link if_index _ < <(get_link_info "$dev"); then + usage "Invalid device name: '$dev'" + return 1 + fi + + busctl_status &> /dev/null || { + local -i status="$?" + err << ERR +systemd-resolved DBus interface (${DBUS_DEST}) is not available. +$SCRIPT_NAME requires systemd version 229 or above. +ERR + return "$status" + } + + if ! "$func" "$link" "$if_index" "$@"; then + err 'Unable to configure systemd-resolved.' + return 1 + fi +} + +_up() { + local link="$1" + shift + local if_index="$1" + shift + + info "Link '$link' coming up" + + # Preset values for processing -- will be altered in the various process_* + # functions. + local -a dns_servers=() dns_ex_servers=() dns_domain=() dns_search=() dns_routed=() dnssec_negative_trust_anchors=() + local -i dns_server_count=0 dns_ex_server_count=0 + local flush_caches=yes + local dns_sec reset_statistics reset_server_features default_route + local llmnr multicast_dns dns_over_tls + + # This function is called indirectly below (via `each_dhcp_setting`); disable + # check for unreachable commands. + # shellcheck disable=SC2317 + _dispatch_dhcp_setting() { + local setting_type="${1?}" + local setting_value="${2?}" + + process_setting_function="${setting_type,,}" + process_setting_function="process_${process_setting_function//-/_}" + + if declare -f "$process_setting_function" &> /dev/null; then + "$process_setting_function" "$setting_value" || return $? + else + warning "Not a recognized DHCP setting: '${setting_type}'" + fi + } + + each_dhcp_setting _dispatch_dhcp_setting || return + + if [[ ${reset_statistics-} == yes ]]; then + info "ResetStatistics()" + busctl_call ResetStatistics || return $? + fi + + if [[ ${reset_server_features-} == yes ]]; then + info 'ResetServerFeatures()' + busctl_call ResetServerFeatures || return $? + fi + + if [[ -n ${dns_sec+x} ]]; then + info "SetLinkDNSSEC(${if_index} '${dns_sec}')" + busctl_call SetLinkDNSSEC 'is' "$if_index" "${dns_sec}" || return + fi + + if [[ ${#dns_servers[*]} -gt 0 ]]; then + busctl_params=("$if_index" "$dns_server_count" "${dns_servers[@]}") + info "SetLinkDNS(${busctl_params[*]})" + busctl_call SetLinkDNS 'ia(iay)' "${busctl_params[@]}" || return $? + fi + + if [[ ${#dns_ex_servers[*]} -gt 0 ]]; then + busctl_params=("$if_index" "$dns_ex_server_count" "${dns_ex_servers[@]}") + info "SetLinkDNSEx(${busctl_params[*]})" + busctl_call SetLinkDNSEx 'ia(iayqs)' "${busctl_params[@]}" || return $? + fi + + # Divide by two to account for the boolean second argument + dns_count="$(((${#dns_domain[*]} + ${#dns_search[*]} + ${#dns_routed[*]}) / 2))" + if ((dns_count > 0)); then + busctl_params=( + "$if_index" + "$dns_count" + + # Hack to work around pre-4.4 Bash `empty array == unset` bug + ${dns_domain:+"${dns_domain[@]}"} + ${dns_search:+"${dns_search[@]}"} + ${dns_routed:+"${dns_routed[@]}"} + ) + info "SetLinkDomains(${busctl_params[*]})" + busctl_call SetLinkDomains 'ia(sb)' "${busctl_params[@]}" || return $? + fi + + if [[ -n ${default_route-} ]]; then + info "SetLinkDefaultRoute(${if_index} ${default_route})" + busctl_call SetLinkDefaultRoute 'ib' "$if_index" "$default_route" || return $? + fi + + if [[ -n ${llmnr+x} ]]; then + info "SetLinkLLMNR(${if_index} '${llmnr}')" + busctl_call SetLinkLLMNR 'is' "$if_index" "$llmnr" + fi + + if [[ -n ${multicast_dns+x} ]]; then + info "SetLinkMulticastDNS(${if_index} '${multicast_dns}')" + busctl_call SetLinkMulticastDNS 'is' "$if_index" "$multicast_dns" + fi + + if [[ -n ${dns_over_tls+x} ]]; then + info "SetLinkDNSOverTLS(${if_index} '${dns_over_tls}')" + busctl_call SetLinkDNSOverTLS 'is' "$if_index" "$dns_over_tls" + fi + + if (("${#dnssec_negative_trust_anchors[*]}" > 0)); then + busctl_params=( + "$if_index" + "${#dnssec_negative_trust_anchors[*]}" + "${dnssec_negative_trust_anchors[@]}" + ) + + info "SetLinkDNSSECNegativeTrustAnchors(${busctl_params[*]})" + busctl_call SetLinkDNSSECNegativeTrustAnchors ias "${busctl_params[@]}" + fi + + if [[ -n ${flush_caches-} ]]; then + info 'FlushCaches()' + busctl_call FlushCaches || return + fi +} + +up() { + with_openvpn_script_handling _up "$@" +} + +down() { + with_openvpn_script_handling _down "$@" +} + +_down() { + local link="$1" + shift + local if_index="$1" + shift + + info "Link '$link' going down" + + if ! busctl_call RevertLink i "$if_index"; then + info 'Calling RevertLink failed; this can happen if privileges were dropped in the OpenVPN client.' + print_polkit_rules_command_for_current_user | info + fi +} + +# Run sipcalc and extract a single line matching the provided prefix +match_sipcalc_output() { + usage_for 2 2 "$#" '
' || return + + local prefix="$1" + shift + + local out + out="$(sipcalc "$@" 2> >(err))" || return + + while read -r line; do + if [[ $line == "$prefix"* ]]; then + printf -- '%s\n' "${line##*- }" + return + fi + done <<< "$out" + + return 1 +} + +# Expand an IPv4 or IPv6 address using Python's "ipaddress" module +expand_ip_python() { + usage_for 2 2 "$#" '{IPv4,IPv6}
' || return + + local type="$1" + shift + + case "$type" in + IPv4 | IPv6) ;; + *) + err "${FUNCNAME[0]}: not a valid IP version type: ${type}" + return 64 + ;; + esac + + python -c " +import ipaddress +import sys + +# Abort if we're on an older Python; the backported 'ipaddress' module requires +# IPs to be unicode, and properly decoding sys.argv is problematic on Python 2 +# (see https://bugs.python.org/issue2128). +if sys.version_info < (3, 0): + majmin = '.'.join([str(v) for v in sys.version_info[0:2]]) + sys.stderr.write('${type} address expansion is not supported for Python {0}\\n'.format(majmin)) + sys.exit(1) + +try: + print(ipaddress.${type}Address(sys.argv[1]).exploded) +except Exception as e: + sys.stderr.write(\"'{0}' is not a valid ${type} address: {1}\\n\".format(sys.argv[1], e)) + sys.exit(1) +" "${1?}" 2> >(err) +} + +# Very light check to see if a string looks vaguely in the vicinity of an IPv4 +# address; more robust validation occurs in (the course of executing) +# "parse_ipv4". +# +# NOTE that we include the "! looks_like_ipv6" condition in order return a +# nonzero status when provided an IPv4-in-IPv6 address (e.g. "::ffff:1.2.3.4"). +# This check comes after the check for dotted-quad so that we can do +# +# if looks_like_ipv6 "$address"; then +# process_dns_ipv6 "$address" || return $? +# elif looks_like_ipv4 "$address"; then +# process_dns_ipv4 "$address" || return $? +# else +# +# without repeating work. +looks_like_ipv4() { + [[ ${1-} =~ ^([^.]+\.){3}[^.]+$ ]] && ! looks_like_ipv6 "${1-}" +} + +# Read the components of a dotted-quad IPv4 into the specified array variable +read_ipv4_segments_into() { + usage_for 2 2 "$#" ' ' || return + + split_on_separator_into $'.' "$@" +} + +each_ipv4_segment() { + looks_like_ipv4 "$@" || return + + local -a segments + read_ipv4_segments_into segments "$@" || return + + ((${#segments[@]} == 4)) || return + + local segment + for segment in "${segments[@]}"; do + printf -- '%s\n' "$segment" + done +} + +expand_ipv4_native() { + local address="$1" + + local -a segments + mapfile_from_command -t segments each_ipv4_segment "$address" || return + + log_invalid_ipv4() { + local message="'$address' is not a valid IPv4 address" + err "${message}: $*" + unset -f "${FUNCNAME[0]:-log_invalid_ipv4}" + return 1 + } + + local segment + local -i decimal_segment + + for segment in "${segments[@]}"; do + printf -v decimal_segment -- '%d' "$segment" 2> /dev/null || { + local -i status="$?" + log_invalid_ipv4 "cannot interpret '${segment}' as a decimal number" + return "$status" + } + + if ((decimal_segment < 0)) || ((decimal_segment > 255)); then + log_invalid_ipv4 "'${segment}' is not a decimal number from 0 to 255, inclusive" + return 1 + fi + done + + puts_with_separator $'.' "${segments[@]}" +} + +expand_ipv4_sipcalc() { + match_sipcalc_output 'Host address' "$@" +} + +expand_ipv4_python() { + expand_ip_python IPv4 "$@" +} + +parse_ipv4() { + local expanded + expanded="$(expand_ipv4 "$@")" || return + each_ipv4_segment "$expanded" +} + +# Very light check to see if a string looks vaguely in the vicinity of an IPv6 +# address; more robust validation occurs in (the course of executing) +# "parse_ipv6". +looks_like_ipv6() { + [[ ${1-} == *:*:* ]] +} + +read_ipv6_segments_into() { + usage_for 2 2 "$#" '
' || return + + split_on_separator_into $':' "$@" +} + +each_ipv6_segment() { + looks_like_ipv6 "$@" || return + + local -a segments + read_ipv6_segments_into segments "$@" || return + + ((${#segments[@]} == 8)) || return + + local segment + for segment in "${segments[@]}"; do + printf -- '%s\n' "$segment" + done +} + +expand_ipv6_native() { + local orig_address="${1-}" + + log_invalid_ipv6() { + local message="'$orig_address' is not a valid IPv6 address" + err "${message}: $*" + unset -f "${FUNCNAME[0]:-log_invalid_ipv6}" + return 1 + } + + local -a orig_segments + read_ipv6_segments_into orig_segments "$orig_address" || { + local -i status="$?" + log_invalid_ipv6 'failed to read address segments' + return "$status" + } + + if (("${#orig_segments[@]}" < 3)); then + log_invalid_ipv6 "expected at least 3 address segments; got ${#orig_segments[@]}" + return 1 + fi + + if looks_like_ipv4 "${orig_segments[-1]-}"; then + local -a ipv4_segments + + mapfile_from_command -t ipv4_segments parse_ipv4 "${orig_segments[-1]}" || { + local -i status="$?" + log_invalid_ipv6 "failed to parse embedded IPv4 address '${orig_segments[-1]}'" + return "$status" + } + + printf -v 'orig_segments[-1]' -- '%0.2x%0.2x' "${ipv4_segments[@]:0:2}" + printf -v "orig_segments[${#orig_segments[@]}]" -- '%0.2x%0.2x' "${ipv4_segments[@]:2:4}" + fi + + local -i expected_len=8 + local -i orig_len="${#orig_segments[@]}" + + # "expected_len + 1" to account for addresses like "::1:1:1:1:1:1:1" + if ((orig_len > (expected_len + 1))); then + log_invalid_ipv6 "at most ${expected_len} colons permitted; got $((orig_len - 1))" + return 1 + fi + + local -a final_segments + local final_segment + local -i orig_idx + local saw_compressed_group + local -i zero_segments_needed_count + + for ((orig_idx = 0; orig_idx < orig_len; orig_idx++)); do + orig_segment="${orig_segments[orig_idx]}" + + if [[ -z $orig_segment ]]; then + if [[ -n ${saw_compressed_group-} ]]; then + log_invalid_ipv6 "at most one '::' permitted" + return 1 + fi + + saw_compressed_group=yes + + if ((orig_idx == 0)); then + # ::1:2:3:4 + if [[ -z ${orig_segments[$((orig_idx + 1))]-} ]]; then + zero_segments_needed_count="$(((expected_len - orig_len) + 2))" + ((orig_idx++)) + # :1:2:3:4 + else + log_invalid_ipv6 "leading ':' without '::'" + return 1 + fi + # 1:2:3:4:: + elif { + ((orig_idx == (orig_len - 2))) && + [[ -z ${orig_segments[$((orig_idx + 1))]-} ]] + }; then + zero_segments_needed_count="$(((expected_len - orig_len) + 2))" + ((orig_idx++)) + # 1:2:3:4: + elif ((orig_idx == (orig_len - 1))); then + log_invalid_ipv6 "trailing ':' without '::'" + return 1 + # 1:2::3:4 + else + zero_segments_needed_count="$(((expected_len - orig_len) + 1))" + fi + + if ((zero_segments_needed_count < 1)); then + log_invalid_ipv6 "cannot expand '::'; address already has 8 or more segments" + return 1 + fi + + local -i zero_segment_counter + for ((\ + zero_segment_counter = 0; \ + zero_segment_counter < zero_segments_needed_count; \ + zero_segment_counter++)); do + final_segments+=(0000) + done + elif (("${#orig_segment}" > 4)); then + log_invalid_ipv6 "'$orig_segment' is longer than 4 characters" + return 1 + else + printf -v final_segment -- '%0.4x' "0x${orig_segment}" 2> /dev/null || { + local -i status="$?" + log_invalid_ipv6 "cannot interpret '${orig_segment}' as a hexadecimal number" + return "$status" + } + + final_segments+=("$final_segment") + fi + done + + if (("${#final_segments[@]}" != expected_len)); then + log_invalid_ipv6 "expected ${expected_len} segments; got ${#final_segments[@]}" + return 1 + fi + + puts_with_separator $':' "${final_segments[@]}" +} + +expand_ipv6_sipcalc() { + match_sipcalc_output 'Expanded Address' "$@" +} + +expand_ipv6_python() { + expand_ip_python IPv6 "$@" +} + +test_ipv4_expansion_func() { + local expanded + expanded="$("${1?}" 127.0.0.1)" && [[ $expanded == '127.0.0.1' ]] +} + +test_ipv6_expansion_func() { + local expanded + expanded="$("${1?}" ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff)" && + [[ $expanded == ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ]] +} + +each_ip_expansion_func() { + local cb="$1" + shift + + local type name + + case "${1,,}" in + ipv4) + type="${1,,}" + name=IPv4 + ;; + ipv6) + type="${1,,}" + name=IPv6 + ;; + *) + err "unrecognized IP version type '${1}'" + return 64 + ;; + esac + + local expansion_func="expand_${type}" + local expansion_func_impl + local impl + + for impl in python sipcalc native; do + expansion_func_impl="${expansion_func}_${impl}" + + # Run in subshell with `logger` defined as a NOP to avoid issuing useless + # messages about (say) not being able to find the `python` or `sipcalc` + # programs. + # `log` is called indirectly; disable warning about unreachable command. + # shellcheck disable=SC2317 + if ( + log() { :; } + "test_${type}_expansion_func" "$expansion_func_impl" + ); then + if "$cb" "$expansion_func_impl" 1; then + return + fi + elif "$cb" "$expansion_func_impl" 0; then + return + fi + done +} + +set_up_ip_expansion_func() { + local type name + + case "${1,,}" in + ipv4) + type="${1,,}" + name=IPv4 + ;; + ipv6) + type="${1,,}" + name=IPv6 + ;; + *) + err "unrecognized IP version type '${1}'" + return 64 + ;; + esac + + local preference_var="UPDATE_SYSTEMD_RESOLVED_PREFERRED_${type^^}_EXPANSION_IMPLEMENTATION" + + local preference + if [[ -v $preference_var ]]; then + preference="${!preference_var}" + fi + + preference="${preference:-${UPDATE_SYSTEMD_RESOLVED_PREFERRED_IP_EXPANSION_IMPLEMENTATION-}}" + + local expansion_func="expand_${type}" + + local expansion_func_impl + + if [[ -n $preference ]]; then + expansion_func_impl="${expansion_func}_${preference}" + + if declare -f "$expansion_func_impl" &> /dev/null; then + eval "${expansion_func}() { $expansion_func_impl \"\$@\"; }" + else + err "${preference} is not a valid ${name} address expansion implementation" + exit 1 + fi + fi + + if ! declare -f "$expansion_func" &> /dev/null; then + # This function is called indirectly below (via `each_ip_expansion_func`); + # disable check for unreachable commands. + # shellcheck disable=SC2317 + choose_expansion_func_impl() { + expansion_func_impl="$1" + + if (("$2" == 1)); then + eval "${expansion_func}() { $expansion_func_impl \"\$@\"; }" + else + return 1 + fi + } + + each_ip_expansion_func choose_expansion_func_impl "$type" + + unset -f choose_expansion_func_impl + fi + + if ! declare -f "$expansion_func" &> /dev/null; then + err "no usable ${name} expansion implementations" + return 1 + fi +} + +# "builtin exit" because the test suite overrides "exit". If we cannot handle +# IP addresses, no sense in continuing. +set_up_ip_expansion_func ipv4 || builtin exit +set_up_ip_expansion_func ipv6 || builtin exit + +parse_ipv6() { + local expanded + expanded="$(expand_ipv6 "$@")" || return + each_ipv6_segment "$expanded" +} + +parse_dns_spec() { + usage_for 1 - "$#" ' [ ]' || return + + local spec="$1" + shift + + local -n address_ref="${1:-address}" + shift + + local -n port_ref="${1:-port}" + shift + + local -n server_name_ref="${1:-server_name}" + shift + + local cursor="$spec" + while [[ -n ${cursor-} ]]; do + case "$cursor" in + *'#'?*) + server_name_ref="${cursor#*'#'}" + cursor="${cursor%%'#'*}" + ;; + *:?*) + if looks_like_ipv6 "$cursor" &> /dev/null; then + address_ref="$cursor" + break + else + case "$cursor" in + '['*']'*) + case "$cursor" in + '['*']:'?*) + address_ref="${cursor#[}" + address_ref="${address_ref#]}" + port_ref="${cursor#*:}" + break + ;; + *) + err "invalid DNS server specification '${spec}'" + return 1 + ;; + esac + ;; + *) + address_ref="${cursor%%:*}" + port_ref="${cursor#*:}" + break + ;; + esac + fi + ;; + *) + address_ref="$cursor" + break + ;; + esac + done + + # Ensure that port variable is defined if server name variable is. The + # default value is `0`, meaning "default port 53" when passed to + # `SetLinkDNSEx`. + # + # NOTE that we do not do any further input validation here; instead we let + # `SetLinkDNSEx` complain if the port is anything other than an unsigned + # integer < 2 ** 16. + if [[ -n ${server_name_ref-} ]]; then + port_ref="${port_ref:-0}" + fi + + # Ensure that server name variable is defined if port variable is. The + # default value is the empty string, meaning "no server name" when passed to + # `SetLinkDNSEx`. + if [[ -n ${port_ref-} ]]; then + server_name_ref="${server_name_ref-}" + fi +} + +process_dns() { + local spec="$1" + shift + + local address port server_name + parse_dns_spec "$spec" address port server_name || return + + local -a args=() + if [[ -n ${port-} ]] || [[ -n ${server_name-} ]]; then + args=("${port:-0}" "${server_name-}") + fi + + if looks_like_ipv6 "$address"; then + process_dns_ipv6 "$address" "${args[@]}" || return + elif looks_like_ipv4 "$address"; then + process_dns_ipv4 "$address" "${args[@]}" || return + else + err "Not a valid IPv6 or IPv4 address: '${address}' (full specification: '${spec}')" + return 1 + fi +} + +process_dns6() { + process_dns "$@" +} + +process_dns_ipv4() { + usage_for 1 3 "$#" '
[ ]' || return + + local address="$1" + shift + + info "Adding IPv4 DNS Server ${address}" + + local -a segments + mapfile_from_command -t segments parse_ipv4 "$address" || return + + if (("$#" > 0)); then + dns_ex_servers+=(2 4 "${segments[@]}" "${1:-0}" "${2-}") + ((dns_ex_server_count += 1)) + else + dns_servers+=(2 4 "${segments[@]}") + ((dns_server_count += 1)) + fi +} + +process_dns_ipv6() { + usage_for 1 3 "$#" '
[ ]' || return + + local address="$1" + shift + + info "Adding IPv6 DNS Server ${address}" + + local -a segments + mapfile_from_command -t segments parse_ipv6 "$address" || return + + if (("$#" > 0)); then + # Add AF_INET6 and byte count + dns_ex_servers+=(10 16) + for segment in "${segments[@]}"; do + dns_ex_servers+=("$((16#${segment:0:2}))" "$((16#${segment:2:2}))") + done + + dns_ex_servers+=("${1:-0}" "${2-}") + + ((dns_ex_server_count += 1)) + else + # Add AF_INET6 and byte count + dns_servers+=(10 16) + for segment in "${segments[@]}"; do + dns_servers+=("$((16#${segment:0:2}))" "$((16#${segment:2:2}))") + done + + ((dns_server_count += 1)) + fi +} + +process_domain() { + local domain="$1" + shift + + info "Adding DNS Domain ${domain}" + + # Make sure the first domain specified with "dhcp-option DOMAIN " + # appears at the head of the list we pass to SetLinkDNS. + if (("${#dns_domain[*]}" == 0)); then + dns_domain+=("${domain}" false) + else + dns_search+=("${domain}" false) + fi +} + +process_adapter_domain_suffix() { + # This enables support for ADAPTER_DOMAIN_SUFFIX which is a Microsoft standard + # which works in the same way as DOMAIN to set the primary search domain on + # this specific link. + process_domain "$@" +} + +process_domain_search() { + local domain="$1" + shift + + info "Adding DNS Search Domain ${domain}" + dns_search+=("${domain}" false) +} + +process_domain_route() { + local domain="$1" + shift + + info "Adding DNS Routed Domain ${domain}" + dns_routed+=("${domain}" true) +} + +process_dnssec() { + case "${1,,}" in + yes | true) + dns_sec=yes + ;; + no | false) + dns_sec=no + ;; + allow-downgrade) + dns_sec=allow-downgrade + ;; + default) + dns_sec="" + ;; + *) + err "'$1' is not a valid DNSSEC option" + return 1 + ;; + esac + + info "Setting DNSSEC to ${dns_sec:-default}" +} + +process_reset_statistics() { + case "${1,,}" in + yes | true) + reset_statistics=yes + ;; + no | false) + reset_statistics="" + ;; + *) + err "'$1' is not a valid value for RESET-STATISTICS" + return 1 + ;; + esac +} + +process_flush_caches() { + case "${1,,}" in + yes | true) + flush_caches=yes + ;; + no | false) + flush_caches="" + ;; + *) + err "'$1' is not a valid value for FLUSH-CACHES" + return 1 + ;; + esac +} + +process_reset_server_features() { + case "${1,,}" in + yes | true) + reset_server_features=yes + ;; + no | false) + reset_server_features="" + ;; + *) + err "'$1' is not a valid value for RESET-SERVER-FEATURES" + return 1 + ;; + esac +} + +process_default_route() { + case "${1,,}" in + yes | true) + default_route=true + ;; + no | false) + default_route=false + ;; + *) + err "'$1' is not a valid value for DEFAULT-ROUTE" + return 1 + ;; + esac + + info "Setting DEFAULT-ROUTE to ${default_route}" +} + +process_llmnr() { + case "${1,,}" in + yes | true) + llmnr=yes + ;; + no | false) + llmnr=no + ;; + resolve) + llmnr=resolve + ;; + default) + llmnr="" + ;; + *) + err "'$1' is not a valid value for LLMNR" + return 1 + ;; + esac + + info "Setting LLMNR to ${llmnr:-default}" +} + +process_multicast_dns() { + case "${1,,}" in + yes | true) + multicast_dns=yes + ;; + no | false) + multicast_dns=no + ;; + resolve) + multicast_dns=resolve + ;; + default) + multicast_dns="" + ;; + *) + err "'$1' is not a valid value for MULTICAST-DNS" + return 1 + ;; + esac + + info "Setting MULTICAST-DNS to ${multicast_dns:-default}" +} + +process_dns_over_tls() { + case "${1,,}" in + yes | true) + dns_over_tls=yes + ;; + no | false) + dns_over_tls=no + ;; + opportunistic) + dns_over_tls=opportunistic + ;; + default) + dns_over_tls="" + ;; + *) + err "'$1' is not a valid value for DNS-OVER-TLS" + return 1 + ;; + esac + + info "Setting DNS-OVER-TLS to ${dns_over_tls:-default}" +} + +process_dnssec_negative_trust_anchors() { + local domain="$1" + shift + + info "Adding DNSSEC negative trust anchor ${domain}" + dnssec_negative_trust_anchors+=("$domain") +} + +to_json_array_jq() { + jq --compact-output --null-input '$ARGS.positional' --args -- "$@" +} + +to_json_array_perl() { + perl -MModule::Load -wle ' +foreach my $mod ( qw(Cpanel::JSON::XS JSON::MaybeXS JSON::XS JSON::PP JSON) ) { + if ( eval { load $mod; $mod->import(qw(encode_json)); 1 } ) { + print encode_json(\@ARGV); + last; + } +} + ' -- "$@" +} + +to_json_array_python() { + python -c " +import sys + +try: + import json +except ImportError: + import simplejson as json + +print(json.dumps(sys.argv[1:])) +" "$@" +} + +to_json_array_native() { + printf -- '[' + + while (("$#" > 0)); do + printf -- '"%s"' "${1//\"/\\\"}" + shift + if (("$#" > 0)); then + printf -- ',' + fi + done + + printf -- ']' +} + +test_to_json_array_func() { + local expanded + expanded="$("${1?}" foo bar baz)" && [[ $expanded =~ ^\['"foo",'[[:space:]]*'"bar",'[[:space:]]*'"baz"'\]$ ]] +} + +set_up_to_json_array_func() { + local expansion_func_impl + local impl + + for impl in jq perl python native; do + expansion_func_impl="to_json_array_${impl}" + if test_to_json_array_func "$expansion_func_impl" 2> /dev/null; then + eval "to_json_array() { $expansion_func_impl \"\$@\"; }" + return + fi + done + + return 1 +} + +if ! set_up_to_json_array_func; then + to_json_array_func() { + printf -- 'Unable to serialize arguments to a JSON array' + return 127 + } +fi + +require_optarg() { + local opt="$1" + shift + + local argc="$1" + shift + + if ((argc < 2)); then + err "missing required argument for option \"$opt\"" + return 1 + fi +} + +# shellcheck disable=SC2120 +print_polkit_rules() { + local -A allowed_users_map=() allowed_groups_map=() systemd_openvpn_units_map=() + + while (("$#" > 0)); do + case "$1" in + --polkit-allowed-user) + require_optarg "$1" "$#" || return + allowed_users_map["${2?}"]=1 + shift + ;; + --polkit-allowed-user=?*) + allowed_users_map["${1#*=}"]=1 + ;; + --polkit-allowed-group) + require_optarg "$1" "$#" || return + allowed_groups_map["${2?}"]=1 + shift + ;; + --polkit-allowed-group=?*) + allowed_groups_map["${1#*=}"]=1 + ;; + --polkit-systemd-openvpn-unit) + require_optarg "$1" "$#" || return + systemd_openvpn_units_map["${2?}"]=1 + shift + ;; + --polkit-systemd-openvpn-unit=?*) + systemd_openvpn_units_map["${1#*=}"]=1 + ;; + *) + err "unrecognized option: $1" + return 1 + ;; + esac + + shift + done + + if { + (("${#systemd_openvpn_units_map[@]}" < 1)) && + (("${#allowed_users_map[@]}" < 1)) && + (("${#allowed_groups_map[@]}" < 1)) + }; then + # NOTE that we cannot use the template unit "openvpn-client@.service" + # itself: + # + # $ systemctl show -p User openvpn-client@.service + # Failed to get properties: Unit name openvpn-client@.service is neither a valid invocation ID nor unit name. + # $ systemctl show -p User openvpn-client@utterly-bogus.service + # User=openvpn + # + systemd_openvpn_units_map["openvpn-client@totally-made-up-to-avoid-collisions-${RANDOM:-12345}.service"]=1 + fi + + local allowed_user + while read -r allowed_user; do + if [[ -n ${allowed_user-} ]]; then + allowed_users_map["$allowed_user"]=1 + fi + done < <(systemctl show -P User "${!systemd_openvpn_units_map[@]}" 2> /dev/null) + + if ((${#allowed_users_map[@]} < 1)); then + warning 'unable to determine the value(s) of "User=..." for OpenVPN client systemd units; assuming "root".' + allowed_users_map[root]=1 + fi + + local allowed_group + while read -r allowed_group; do + if [[ -n ${allowed_group-} ]]; then + allowed_groups_map["$allowed_group"]=1 + fi + done < <(systemctl show -P Group "${!systemd_openvpn_units_map[@]}" 2> /dev/null) + + if ((${#allowed_groups_map[@]} < 1)); then + err 'unable to determine the value(s) of "Group=..." for OpenVPN client systemd units; assuming "root".' + allowed_groups_map[root]=1 + fi + + local allowed_users allowed_groups + allowed_users="$(to_json_array "${!allowed_users_map[@]}")" || return + allowed_groups="$(to_json_array "${!allowed_groups_map[@]}")" || return + + printf -- \ + '/* + * Allow OpenVPN client services to update systemd-resolved settings. + * Added by %s. + */ + +function listToBoolMap(list) { + var result = {}; + + for (var i = 0; i < list.length; i++) { + var item = list[i]; + result[item] = true; + } + + return result; +} + +const updateSystemdResolved = { + allowedUsers: listToBoolMap(%s), + + allowedGroups: %s, + + allowedSubactions: listToBoolMap([ + "set-dns-servers", + "set-domains", + "set-default-route", + "set-llmnr", + "set-mdns", + "set-dns-over-tls", + "set-dnssec", + "set-dnssec-negative-trust-anchors", + "revert" + ]), + + actionIsAllowed: function(action) { + if ( !action.id.startsWith("org.freedesktop.resolve1.") ) { + return false; + } + + var ns = action.id.split("."); + var subaction = ns[ns.length - 1]; + + return this.allowedSubactions[subaction]; + }, + + subjectIsAllowed: function(subject) { + if ( this.allowedUsers[subject.user] ) { + return true; + } + + return this.allowedGroups.some(function(group) { + subject.isInGroup(group); + }); + }, + + isAllowed: function(action, subject) { + return this.actionIsAllowed(action) && this.subjectIsAllowed(subject); + } +}; + +polkit.addRule(function(action, subject) { + if ( updateSystemdResolved.isAllowed(action, subject) ) { + return polkit.Result.YES; + } else { + return polkit.Result.NOT_HANDLED; + } +}); +' "$SCRIPT_NAME" "$allowed_users" "$allowed_groups" +} + +print_polkit_rules_command_for_current_user() { + local current_user current_group + + local format='You may wish to add the output of the following command' + format+=' to your polkit rules in order to authorize your user to access' + format+=' the systemd-resolved DBus interface:' + format+='\n%q print-polkit-rules' + + local -a args=("$SCRIPT_NAME") + + if current_user="$(id -u -n 2> /dev/null)" && [[ -n ${current_user-} ]]; then + format+=' --polkit-allowed-user %q' + args+=("$current_user") + fi + + if current_group="$(id -g -n 2> /dev/null)" && [[ -n ${current_group-} ]]; then + format+=' --polkit-allowed-group %q' + args+=("$current_group") + fi + + format+='\nPlease see %s for additional details on configuring polkit.\n' + args+=('https://github.com/tomeon/update-systemd-resolved/tree/polkit-rules-definition#policykit-rules') + + # shellcheck disable=SC2059 + printf -- "$format" "${args[@]}" +} + +main() { + local action + while (("$#" > 0)); do + case "$1" in + up | down | print-polkit-rules) + action="$1" + ;; + --) + shift + break + ;; + *) + break + ;; + esac + + shift + done + + action="${action:-${script_type:-down}}" + action="${action//-/_}" + + if ! declare -f "${action}" &> /dev/null; then + usage "Invalid script type: '${action}'" + return 1 + fi + + "$action" "$@" +} + +if [[ ${BASH_SOURCE[0]} == "$0" ]] || [[ ${AUTOMATED_TESTING-} == 1 ]]; then + set -o nounset + + main "$@" +fi diff --git a/usr/etc/openvpn/update-resolv-conf b/usr/etc/openvpn/update-resolv-conf new file mode 100644 index 0000000..16622a1 --- /dev/null +++ b/usr/etc/openvpn/update-resolv-conf @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +# +# Parses DHCP options from openvpn to update resolv.conf +# To use set as 'up' and 'down' script in your openvpn *.conf: +# up /etc/openvpn/update-resolv-conf +# down /etc/openvpn/update-resolv-conf +# +# Used snippets of resolvconf script by Thomas Hood +# and Chris Hanson +# Licensed under the GNU GPL. See /usr/share/common-licenses/GPL. +# 07/2013 colin@daedrum.net Fixed intet name +# 05/2006 chlauber@bnc.ch +# +# Example envs set from openvpn: +# foreign_option_1='dhcp-option DNS 193.43.27.132' +# foreign_option_2='dhcp-option DNS 193.43.27.133' +# foreign_option_3='dhcp-option DOMAIN be.bnc.ch' +# foreign_option_4='dhcp-option DOMAIN-SEARCH bnc.local' + +## The 'type' builtins will look for file in $PATH variable, so we set the +## PATH below. You might need to directly set the path to 'resolvconf' +## manually if it still doesn't work, i.e. +## RESOLVCONF=/usr/sbin/resolvconf +export PATH=$PATH:/sbin:/usr/sbin:/bin:/usr/bin +RESOLVCONF=$(type -p resolvconf) + +case $script_type in + +up) + for optionname in ${!foreign_option_*} ; do + option="${!optionname}" + echo $option + part1=$(echo "$option" | cut -d " " -f 1) + if [ "$part1" == "dhcp-option" ] ; then + part2=$(echo "$option" | cut -d " " -f 2) + part3=$(echo "$option" | cut -d " " -f 3) + if [ "$part2" == "DNS" ] ; then + IF_DNS_NAMESERVERS="$IF_DNS_NAMESERVERS $part3" + fi + if [[ "$part2" == "DOMAIN" || "$part2" == "DOMAIN-SEARCH" ]] ; then + IF_DNS_SEARCH="$IF_DNS_SEARCH $part3" + fi + fi + done + R="" + if [ "$IF_DNS_SEARCH" ]; then + R="search " + for DS in $IF_DNS_SEARCH ; do + R="${R} $DS" + done + R="${R} +" + fi + + for NS in $IF_DNS_NAMESERVERS ; do + R="${R}nameserver $NS +" + done + #echo -n "$R" | $RESOLVCONF -x -p -a "${dev}" + echo -n "$R" | $RESOLVCONF -x -a "${dev}.inet" + ;; +down) + $RESOLVCONF -d "${dev}.inet" + ;; +esac + +# Workaround / jm@epiclabs.io +# force exit with no errors. Due to an apparent conflict with the Network Manager +# $RESOLVCONF sometimes exits with error code 6 even though it has performed the +# action correctly and OpenVPN shuts down. +exit 0 diff --git a/usr/etc/resolv.conf b/usr/etc/resolv.conf new file mode 100644 index 0000000..b61303e --- /dev/null +++ b/usr/etc/resolv.conf @@ -0,0 +1,4 @@ +nameserver 1.1.1.1 +nameserver 8.26.56.26 +nameserver 208.67.222.222 +nameserver 209.244.0.3 diff --git a/usr/etc/systemd/resolved.conf b/usr/etc/systemd/resolved.conf new file mode 100644 index 0000000..68fcb8d --- /dev/null +++ b/usr/etc/systemd/resolved.conf @@ -0,0 +1,44 @@ +# This file is part of systemd. -> systemctl enable --now systemd-resolved +# +# systemd is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 2.1 of the License, or (at your option) +# any later version. +# +# Entries in this file show the compile time defaults. Local configuration +# should be created by either modifying this file (or a copy of it placed in +# /etc/ if the original file is shipped in /usr/), or by creating "drop-ins" in +# the /etc/systemd/resolved.conf.d/ directory. The latter is generally +# recommended. Defaults can be restored by simply deleting the main +# configuration file and all drop-ins located in /etc/. +# +# Use 'systemd-analyze cat-config systemd/resolved.conf' to display the full config. +# +# See resolved.conf(5) for details. + +[Resolve] +# Some examples of DNS servers which may be used for DNS= and FallbackDNS=: +DNS=1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001 #cloudflare-dns.com +# Quad9: 9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net +FallbackDNS=193.110.81.0 185.253.5.0 2a0f:fc80:: 2a0f:fc81:: #dns0.eu +# +# Using DNS= configures global DNS servers and does not suppress link-specific +# configuration. Parallel requests will be sent to per-link DNS servers +# configured automatically by systemd-networkd.service(8), NetworkManager(8), or +# similar management services, or configured manually via resolvectl(1). See +# resolved.conf(5) and systemd-resolved(8) for more details. +#DNS= +#FallbackDNS=9.9.9.9#dns.quad9.net 2620:fe::9#dns.quad9.net 1.1.1.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 8.8.8.8#dns.google 2001:4860:4860::8888#dns.google +#Domains= +DNSSEC=yes +DNSOverTLS=yes +MulticastDNS=yes +LLMNR=yes +Cache=yes +CacheFromLocalhost=no +DNSStubListener=yes +#DNSStubListenerExtra= +ReadEtcHosts=yes +#ResolveUnicastSingleLabel=no +#StaleRetentionSec=0 +#RefuseRecordTypes= diff --git a/usr/etc/systemd/system/tcpd.service b/usr/etc/systemd/system/tcpd.service new file mode 100644 index 0000000..9689c83 --- /dev/null +++ b/usr/etc/systemd/system/tcpd.service @@ -0,0 +1,12 @@ +[Unit] +Description=watch connections +After=network-online.target + +[Service] +ExecStart=/bin/bash /etc/systemd/system/tcpd.sh +After=tcpd-bkup.service +Type=simple + +[Install] +WantedBy=multi-user.target + diff --git a/usr/etc/systemd/system/tcpd.sh b/usr/etc/systemd/system/tcpd.sh new file mode 100755 index 0000000..9ea523a --- /dev/null +++ b/usr/etc/systemd/system/tcpd.sh @@ -0,0 +1,10 @@ +#!/usr/bin/bash + +. /etc/env + +mkdir -p $LOG_CONN_DIR +tcpdump -n -l > $LOG_CONN + +exit 0 + + diff --git a/usr/etc/systemd/system/tcpd_bkup.sh b/usr/etc/systemd/system/tcpd_bkup.sh new file mode 100755 index 0000000..f341507 --- /dev/null +++ b/usr/etc/systemd/system/tcpd_bkup.sh @@ -0,0 +1,21 @@ +#!/usr/bin/bash +#run from crontab + +. /home/.bashrc + +. refresh_time + +STATUS=ronron +if [ -f $NET_STATUS ] ; then + STATUS=$(cat $NET_STATUS) +fi + +DIR=$LOG_CONN_DIR/$STATUS +mkdir -p $DIR +grepip $LOG_CONN > $DIR/${DATE}_${TIME}.conn +mv -f $LOG_CONN $LOG_CONN_DIR/prev.log +systemctl restart tcpd + +exit 0 + + diff --git a/usr/home/.bash_aliases b/usr/home/.bash_aliases new file mode 100644 index 0000000..8af0a68 --- /dev/null +++ b/usr/home/.bash_aliases @@ -0,0 +1,643 @@ +# enable color support of ls and also add handy aliases +if [ -x /usr/bin/dircolors ]; then + test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" + alias ls='ls --color=auto' + alias dir='dir --color=auto' + alias vdir='vdir --color=auto' + + alias grep='grep --color=auto' + alias fgrep='fgrep --color=auto' + alias egrep='egrep --color=auto' +fi + +# colored GCC warnings and errors +#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01' + +# some more ls aliases +alias ll='ls -alFh' +alias la='ls -A' +alias l='ls -CF' + + +alias ccc="cc -Wall -Wextra -Werror $@" +alias val="valgrind --leak-check=full --show-leak-kinds=all" +alias mvj='rsync -aH --remove-source-files' +alias cpj='rsync -aH' +alias git_light="git filter-repo --strip-blobs-bigger-than 10M" +alias src="source ~/.bashrc" +alias s="sudo -E" + +##convert mp3 to wav +#to_wav () { +# OUTDIR_NAME="wav_files" +# #mkdir $OUTDIR_NAME +# for file in "$@" ; do +# WAV_NAME=${file%.*}.wav +# echo $file +# echo +# ffmpeg -i $file -ar 16000 -ac 1 "$WAV_NAME" +# done +#} +# +##convert wav to mp3 +#to_mp3 () { +# #OUTDIR_NAME="wav_files" +# #mkdir $OUTDIR_NAME +# for file in "$@" ; do +# MP3_NAME=${file%.*}.mp3 +# echo $file +# echo +# ffmpeg -i $file -vn -b:a 192k "$MP3_NAME" +# done +#} +# +#cexec () { +# BASE=($@) +# NAME="${BASE%.*}" +# FLAGS=('-Wall' '-Wextra' '-Werror') +# cc ${FLAGS[@]} $BASE -o "$NAME" && ./"$NAME" && rm $NAME +#} +# +#cdebug () { +# BASE="$1" +# NAME="${BASE%.*}" +# FLAGS="-g3" +# cc $BASE $FLAGS -o "$NAME" && gdb "$NAME" && rm $NAME +#} +# +#brc () { +# SOURCE="$HOME/.bashrc" +# F_NAME=".bashrc" +# FILE="$(find -O3 $HOME -name $F_NAME 2>/dev/null | head -n 1)" +# F_PATH="$(dirname $FILE)" +# cd "$F_PATH" +# commit_if_modified "$F_NAME" +# cd - +# source $SOURCE +#} +# +#vrc () { +# SOURCE="$HOME/.vimrc" +# F_NAME=".bash_aliases" +# FILE="$(find -O3 $HOME -name $F_NAME 2>/dev/null | head -n 1)" +# F_PATH="$(dirname $FILE)" +# cd "$F_PATH" +# commit_if_modified "$F_NAME" +# cd - +# source $SOURCE +#} +#basha () { +# SOURCE="$HOME/.bashrc" +# F_NAME=".bash_aliases" +# FILE=$HOME/$F_NAME +# cd "$HOME/machine" +# commit_if_modified "$FILE" +# cd - +# source $SOURCE +#} +# +#machine_install () { +# FILE=~/machine/install.sh +# vim $FILE +# cd $FILE +# git add $FILE +# git commit -m "$FILE install mofified" +# git push +# cd - +#} +# +#arch_install () { +# FOLD=~/machine +# FILE=$FOLD/arch_install.sh +# vim $FILE +# cd $FOLD +# git add $FILE +# git commit -m "$FILE install mofified" +# git push +# cd - +#} +# +#netstat_tunlp () { +# netstat -tunlp +#} +# +#nmap_full () { +# sudo nmap --scanflags URGACKPSHRSTSYNFIN $@ +#} +# +#nmap_sA () { +##ACK scan: the target would respond to the ACK with RST regardless of the state of the port +##help to guess firewall rules if the packet is droped +# nmap -sA --reason #or -v -vv -d -dd +#} +# +#nmap_version () { +# #-O = OS detection +# #-sV services versions +# #version intensity max +# #-sC use default script +# nmap -sV --version-intensity 9 -O -sC $@ +#} +# +#nmap_ssh_brute () { +# nmap --script "ssh-brute" $1 #--script-args userdb=user_list.txt,passdb=passwd_list.txt +#} +# +#gitmain () { +# if [ -z "$1" ]; then +# git checkout main +# git reset --hard "$1" +# git push origin main --force +# fi +#} +# +#gitadd () { +# make fclean +# git add . +#} +# +#gitaddcommit () { +# gitadd +# if [ -n "$1" ]; then +# git commit -m "$1" +# else +# git commit +# fi +#} +# +#gitotal () { +# gitaddcommit $@ +# git pull +# if [ -n "$?" ] ; then +# git push origin HEAD +# fi +#} +# +#gitlog () { +# git log --oneline --decorate --graph --all +#} +# +#aur () { +# git clone https://aur.archlinux.org/$1.git +#} +# +#history_full () { +# HIST_FILE=~/.history +# # => cat ~/.history | head -4 +# # git diff +# # #1741473628 +# # make && lldb ./push_swap +# # #1741474988 +# while read LINE; do +# if [ -n "$(echo "$LINE" | grep '^#')" ]; then +# date -d "$(echo $LINE | sed 's/\#/@/g')" +# else +# echo "$LINE" +# fi +# done < $HIST_FILE +#} +# +#normi () { +# norminette -R CheckForbiddenSourceHeader -R CheckDefine $1 +#} +# +# +#ulog_sort () { +# sudo grep -Eo "MAC.*DST=[^ ]*" /var/log/ulogd.syslogemu | sort | uniq -c | sort -n +# +#} +# +#header_awk () { +# grep -RE $CFUNCTION src | cut -d: -f2 | sed s/\$/';'/g +#} +# +#clone () { +# if [ $# -eq "3" ] ; then +# PROFIL_NAME="$1" +# PROJECT_NAME="$2" +# git clone https://github.com/$PROFIL_NAME/$PROJECT_NAME.git +# else +# PROJECT_NAME="$1" +# git clone git@github.com:nidionis/$PROJECT_NAME.git +# fi +#} +# +#iptables_update () { +# F_PATH="$(dirname $FILE)" +# F_PERSISTENT="/etc/iptables.rules" +# FILE="$(find /home -name 'iptables_script.sh' | head -1)" +# F_TMP=/etc/iptables.rules.backup +# sudo cp $F_PERSISTENT > $F_TMP +# vim + $FILE +# sudo ./$FILE -s -f ip_to_ban.txt -r +# sudo iptables-save > $HOME/tmp +# sudo mv $HOME/tmp $F_PERSISTENT +#} +# +#bashalias () +#{ +# vim ~/.bash_aliases +#} +# +#bashrc () +#{ +# vim ~/.bashrc +#} +# +# +#uniqq () +#{ +# for F in $@ ; do +# sort $F | uniq -c | sort -nr +# done +#} +# +#testee () +#{ +# if [ "$#" -gt 2 -o "$#" -eq 0 ]; then +# echo "Usage: $0 [path/to] " +# echo "default file path is journal/not_sorted/$(date +%F)_${USER}_${$HOST}_${$PWD}.txt" +# return 1 +# fi +#} +# +#journal-perso () +#{ +# refresh_time +# DIR_ORIGINAL=$PWD +# DIR="$HOME/perso" +# DATE_DIR="$YEAR/$MONTH/$DAY" +# if [ "$#" -eq 0 ]; then +# echo "Usage: $0 [ subfolder ] < file >" +# echo "default path is $DIR" +# echo "default file name is $F_NAME" +# return 1 +# fi +# if [ "$#" -eq 1 ]; then +# LN_DIR="fouretout" +# F_NAME=$1 +# fi +# if [ "$#" -eq 2 ]; then +# LN_DIR="$1" +# F_NAME=$2 +# else +# return 1 +# fi +# F_NAME+=".md" +# cd $DIR +# PATH_="${DATE_DIR}/${LN_DIR}" +# mkdir -p "$PATH_" +# FILE="${PATH_}/${F_NAME}" +# header_journal $FILE +# if commit_if_modified $FILE ; then +# mkdir -p "$DIR/$LN_DIR" +# ln -P "$FILE" "$DIR/$LN_DIR/" +# else +# rm $FILE +# rmdir -p "${PATH_}" +# fi +# cd $DIR_ORIGINAL +#} +# +#journal () +#{ +# refresh_time +# DIR_ORIGINAL=$PWD +# DIR="$HOME/journal" +# DATE_DIR="$YEAR/$MONTH/$DAY" +# if [ "$#" -eq 0 ]; then +# echo "Usage: $0 [ subfolder ] < file >" +# echo "default path is $DIR" +# echo "default file name is $F_NAME" +# return 1 +# fi +# if [ "$#" -eq 1 ]; then +# LN_DIR="fouretout" +# F_NAME=$1 +# fi +# if [ "$#" -eq 2 ]; then +# LN_DIR="$1" +# F_NAME=$2 +# else +# return 1 +# fi +# F_NAME+=".md" +# cd $DIR +# PATH_="${DATE_DIR}/${LN_DIR}" +# mkdir -p "$PATH_" +# FILE="${PATH_}/${F_NAME}" +# header_journal $FILE +# if commit_if_modified $FILE ; then +# mkdir -p "$DIR/$LN_DIR" +# ln -P "$FILE" "$DIR/$LN_DIR/" +# else +# rm $FILE +# rmdir -p "${PATH_}" +# fi +# cd $DIR_ORIGINAL +#} +# +#ps_parents () +#{ +# if [ "$#" -ne 1 ]; then +# echo "Usage: $0 " +# return 1 +# fi +# pid=$1 +# while [ "$pid" -ne 1 ]; do +# ps -p $pid -o pid=,ppid=,cmd=; +# pid=$(ps -p $pid -o ppid= --no-headers); +# done +#} +# +#kill_all () +#{ +# if [ -z "$1" ]; then +# echo "Usage: $0 " +# exit 1 +# fi +# +# KEYWORD="$1" +# ps aux | grep "$KEYWORD" | grep -v "grep" | awk '{print $2}' | xargs -r kill -9 +#} +# +#gcl () +#{ +# git clone $1 $2 +#} +# +#src () +#{ +# source $HOME/.bashrc +#} +# +## from https://wiki.alpinelinux.org/wiki/Installing_Alpine_in_a_virtual_machine +#alpine_launch () +#{ +# DIR="$HOME"/alpine +# FILE=$(find $DIR -iregex ".*alpine.*86_64.iso") +# #FILE="$DIR"/alpine-standard*iso +# qemu-system-x86_64 -m 512 -nic user,hostfwd=tcp::2222-:22 -boot d -cdrom $FILE -hda alpine.qcow2 -enable-kvm #-display gtk +#} +# +#compose () +#{ +# docker compose up --watch +#} +# +#cert_local () +#{ +# DIR=${1:-"certs"} +# +# mkdir -p $DIR +# openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ +# -keyout $DIR/localhost.key \ +# -out $DIR/localhost.crt \ +# -subj "/CN=localhost" +#} +# +#virtual() { +# if [ -z "$1" ]; then +# echo "Usage: virtual [arguments supplémentaires pour QEMU]" +# return 1 +# fi +# ISO="$1" +# shift +# if [ ! -f "$ISO" ]; then +# echo "Erreur : fichier '$ISO' introuvable." +# return 1 +# fi +# +# qemu-system-x86_64 $ISO \ +# -enable-kvm \ +# -m 2048 \ +# -cpu host \ +# -cdrom "$ISO" \ +# -boot d \ +# -vga virtio \ +# -nic user \ +# "$@" +#} +# +#refresh_time () { +# export DATE=$(date +"%y%m%d") +# export TIME=$(date +"%T") +#} +# +#header_journal () { +# F_NAME=$1 +# echo "$DATE" >> $F_NAME +# echo "$TIME" >> $F_NAME +# echo "$USER" >> $F_NAME +# echo "$HOST" >> $F_NAME +# echo >> $F_NAME +# echo "###############################################" >> $F_NAME +# echo >> $F_NAME +# echo "$F_NAME" >> $F_NAME +# echo >> $F_NAME +#} +# +#journalctl_prettyfy () { +# SIZE=${1:-"100"} +# UNIQ_MIN=${2:-"1"} +# BOOT=${3:-"0"} +# local TMP="/tmp/journalctl_prettyf.tmp" +# _FILE=${4:-"$TMP"} +# +# CMD="sudo journalctl -b ${BOOT} | tail -n $SIZE" +# CMD_SORTED="${CMD} | cut -d\: -f 4- | sort | uniq -c | sort -n" +# rm -f "$TMP" +# append_cmd "$CMD" "$TMP" +# append_cmd "$CMD_SORTED" "$TMP" +# grep -vE " +[0-${UNIQ_MIN}] " $TMP >> "$_FILE" +# if ! $# ; then cat $_FILE ; fi +# rm "$TMP" +#} +# +#append_cmd () { +# local CMD=$1 +# local F_NAME=$2 +# echo >> $F_NAME +# echo ${CMD} >> $F_NAME +# echo >> $F_NAME +# +# eval ${CMD} >> $F_NAME +# echo >> $F_NAME +# echo "###############################################" >> $F_NAME +# echo >> $F_NAME +#} +# +#commit_if_modified () { +# local F_NAME=$1 +# local DEL=$2 +# git pull +# vim + $F_NAME +# git add $F_NAME +# if ! git commit ; then +# echo -n "[no modifications]" +# if [ -n "$DEL" ] ; then +# rm $F_NAME +# echo -n " -> deleted" +# return 1 +# fi +# fi +# git push +# return 0 +#} +# +#report_crash () +#{ +# refresh_time +# NAME=$1 +# TAIL_SIZE="100" +# DIR_ORIGINAL=$PWD +# CRASH_DIR="$(echo ${DATE}_${TIME} | sed 's/:/-/g')" +# F_NAME="${NAME}.crash" +# DIR_RELATIVE="$HOME/journal/sysadmin/crash" +# DIR_RELATIVE+="/${CRASH_DIR}" +# if [ "$#" -ne 1 ]; then +# echo "Usage: $0 FILE_NAME" +# echo "default path is $DIR_RELATIVE/FILE_NAME.crash" +# echo "write log outputs" +# return 1 +# fi +# +# mkdir -p $DIR_RELATIVE +# cd $DIR_RELATIVE +# if [ -f $F_NAME ] ; then +# BCK="/tmp/$F_NAME.backup" +# echo "File exists moved to $BCK" +# mv $F_NAME $BCK +# fi +# header_journal $F_NAME +# journalctl_prettyfy "100" "1" "0" "$F_NAME" +# commit_if_modified "$F_NAME" "DELETE_IF_NOT_MODIFIED" +# cd $DIR_ORIGINAL +#} +# +#report_last_boot () +#{ +# refresh_time +# NAME=$1 +# DIR_ORIGINAL=$PWD +# CRASH_DIR="$(echo ${DATE}_${TIME} | sed 's/:/-/g')" +# F_NAME="${NAME}.crash" +# DIR_RELATIVE="$HOME/journal/sysadmin/crash/reboot" +# DIR_RELATIVE+="/${CRASH_DIR}" +# if [ "$#" -ne 1 ]; then +# echo "Usage: $0 FILE_NAME" +# echo "default path is $DIR_RELATIVE/${CRASH_DIR}/FILE_NAME.crash" +# echo "write log outputs" +# return 1 +# fi +# +# mkdir -p $DIR_RELATIVE +# cd $DIR_RELATIVE +# header_journal $F_NAME +# journalctl_prettyfy 500 5 1 $F_NAME +# journalctl_prettyfy 10000 5 0 $F_NAME +# commit_if_modified "$F_NAME" "DELETE_IF_NOT_MODIFIED" +# cd $DIR_ORIGINAL +#} +# +#mediaspi () +#{ +# if [ -z $1 ] ; then +# echo "usage: $0 $DIR_NAME" +# return 1 +# fi +# BINAME="collector_bin" +# DEST="$HOME/perso/${BINAME}" +# DIR="${1}" +# mkdir -p $DEST +# mkdir $DIR +# if [ $? -ne 0 ] ; then +# echo "$DIR exists, must be deleted (will be anyway)" +# return 1 +# fi +# find . -type f -regextype egrep -iregex ".*$MEDIA_REG" -exec cp --parents -u {} -t $DIR \; +# cp -apu $DIR -t $DEST +# rm -rf $DIR +#} +# +#conn () { +# sudo cat /var/log/connection_attempts.log +#} +# +#sortu() { +# sort | uniq -c | sort -n +#} +# +#expresso () { +# DIR="$HOME/perso/thm/interets/jeux/poker" +# HISTORY="expresso_history.md" +# SCRIPT=expresso_stat.sh +# TAIL=${1:-1000} +# +# vim + $DIR/$HISTORY +# bash $DIR/$SCRIPT $DIR/$HISTORY $TAIL +#} +# +# +#git_list_heavy_commits () { +# git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n -r | head -n 20 +#} +# +#git_list_heavy () { +# for B in $(git_list_heavy_commits | cut -d' ' -f1) ; do git rev-list --all | while read commit; do git ls-tree -rl $commit; done | grep $B ; done +#} +# +#git_rm_repo () { +# KEYWORD=$1 #ex: '*.mp4' +# git filter-repo --path-glob "$KEYWORD" --invert-paths +#} +# +# +# +# +#monip () { +# curl ifconfig.me +#} +# +#ipinfo () { +# curl https://ipinfo.io/$1 +#} +# +#remote () { +# USER=${1:-$LOGNAME} +# HOST=${2:-"37.187.180.32"} +# PORT=${3:-"9191"} +# sudo -u $USER ssh -l $USER -i /home/$USER/.ssh/id_rsa -p $PORT $HOST +#} +# +#remote_copy () { +# ITEM=${1:-""} +# USER=${2:-$LOGNAME} +# HOST=${3:-"37.187.180.32"} +# PORT=${4:-"9191"} +# if [ -z "$ITEM" ] ; then +# return 1 +# fi +# sudo -u $USER scp -i /home/$USER/.ssh/id_rsa -P $PORT -r $ITEM $USER@$HOST:$ITEM +#} +# +#grepip () { +# grep -E $IP_REG -o $1 | sortu +#} +# +#edit-bin () { +# BIN_PATH=${BIN_PATH:-$HOME/bin} +# FILENAME=$1 +# TEMPLATE=~/.vim/templates/template.my_aliases +# +# if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then +# echo "Usage: $0 alias_name" +# return 1 +# fi +# +# cd $BIN_PATH +# [ ! -f "$FILENAME" ] && cp "$TEMPLATE" "$FILENAME" +# commit_if_modified $FILENAME +# chmod +x $FILENAME +# cd - +#} diff --git a/usr/home/.bashrc b/usr/home/.bashrc new file mode 100644 index 0000000..7e4714c --- /dev/null +++ b/usr/home/.bashrc @@ -0,0 +1,142 @@ +# ~/.bashrc: executed by bash(1) for non-login shells. +# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) +# for examples + + +if [ -f /etc/env ]; then + set -a + . /etc/env + set +a +fi + +set -o vi +export EDITOR="vim" + +export DATE=$(date +"%y%m%d") +export TIME=$(date +"%T") +export YEAR=$(date +"%Y") +export MONTH=$(date +"%m") +export DAY=$(date +"%d") +export USER=$(whoami) +export HOST=$(cat /etc/hostname) +export PWD_=$(pwd) +export SOURCE="$HOME/.bashrc" + + +export OCTET="(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" +export IPV4_REG="($OCTET\.){3}$OCTET" +export IPV6_REG="(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))" +export IP_REG="($IPV4_REG)|($IPV6_REG)" + +MAC_REG='([0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}' + +export YES_REG="\$y\$[./A-Za-z0-9]+\$[./A-Za-z0-9]{,86}\$[./A-Za-z0-9]{43}" +export FILE_REG="[a-zA-Z0-9]+\.[a-zA-Z0-9]+" +export YYYY_REG="((19[5-9][0-9])|(20[0-2][0-9]))" +export MM_REG="((0?[1-9])|(1[0-2]))" +export DD_REG="((0?[1-9])|([1-2][0-9])|(3[0-1]))" +export DATE_REG="(${YYYY_REG}${MM_REG}${DD_REG})|(${DD_REGMM_REG}${YYYY_REG})" +export YYYYMMDD_REG="${YYYY_REG}${MM_REG}${DD_REG}" +export DDMMYYYY_REG="${DD_REG}${MM_REG}${YYYY_REG}" +export CFUNCTION="^[a-z].*\)$" + +# --- Media File Extension Regex Patterns --- +export AUDIO_REG="mp3|wav|ogg|flac|m4a|aac|aiff|opus" +export VIDEO_REG="mp4|mkv|mov|avi|webm|wmv|flv|mpeg|mpg|3gp|m4v" +export IMAGE_REG="jpg|jpeg|png|gif|bmp|webp|tiff|ico|heic|svg|jfif" + +export MEDIA_REG="\.(${AUDIO_REG}|${VIDEO_REG}|${IMAGE_REG})$" + +PATH="/bin:/sbin:/usr/bin:/usr/sbin" +PATH="$PATH:$SBIN_DIR" +PATH="$PATH:$BIN_DIR" +export PATH + +export WWAN="$(ip link | grep -Eo "wwp[a-z0-9]+")" +export WLAN="$(ip link | grep -Eo "wlan[a-z0-9]+")" + +case $- in + *i*) ;; + *) return;; +esac +#. /etc/bash.bashrc + + +# don't put duplicate lines or lines starting with space in the history. +# See bash(1) for more options +# append to the history file, don't overwrite it +#shopt -s histappend +PROMPT_COMMAND='history -a' +export HISTTIMEFORMAT='%F %T ' + +# for setting history length see HISTSIZE and HISTFILESIZE in bash(1) +HISTSIZE=1000 +HISTFILESIZE=2000 +HISTFILE=~/.history + +## check the window size after each command and, if necessary, +## update the values of LINES and COLUMNS. +##shopt -s checkwinsize +# +## If set, the pattern "**" used in a pathname expansion context will +## match all files and zero or more directories and subdirectories. +##shopt -s globstar +# +## make less more friendly for non-text input files, see lesspipe(1) +#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" + +# Définir les couleurs +GREEN='\[\e[32m\]' +YELLOW='\[\e[33m\]' +ORANGE='\[\e[38;5;214m\]' # Il n'y a pas de code direct pour l'orange, mais ce code ANSI s'en approche +RED='\[\e[31m\]' +NO_COLOR='\[\e[0m\]' # Réinitialiser la couleur +# Définir PS1 avec les couleurs +#export PS1="\n\u@\H-\D{%y%m%d}-\t-\w\n=>" +# Couleurs +USER_COLOR="\[\e[1;32m\]" # Vert clair pour l'utilisateur +HOST_COLOR="\[\e[1;34m\]" # Bleu clair pour l'hôte +DATE_COLOR="\[\e[1;33m\]" # Jaune pour la date +TIME_COLOR="\[\e[1;36m\]" # Cyan pour l'heure +DIR_COLOR="\[\e[1;35m\]" # Magenta clair pour le répertoire +RESET_COLOR="$NO_COLOR" + +export GIT_EDITOR=vim + +BRANCH="$(git rev-parse --abbrev-ref HEAD)" +PS1="\n${DATE_COLOR}\D{%y%m%d}${RESET_COLOR}-${TIME_COLOR}\t${RESET_COLOR}-${USER_COLOR}\u${RESET_COLOR}@${HOST_COLOR}\H${RESET_COLOR}-${DIR_COLOR}\w${RESET_COLOR}\n=> " + +export HISTCONTROL=ignorespace + +DEVICE="$(ip addr | grep -v DOWN | grep -E "^[0-9]" | awk -F':' '{print $2}' | grep -v lo)" + +export REMOTE_BRANCHES="github origin" + +export LESS=-R + +export AWK_GREP_KEY="'{ + for (i = 1; i <= NF; i++) + if ($i ~ "^"key"=") { + split($i, a, "=") + print a[2] + } +}'" + +#ctags -R . + +bind -f /home/.inputrc + + +if [ -f /home/.bash_aliases ]; then + . /home/.bash_aliases +fi + +# permet les accents +setxkbmap us -variant intl +source $PY_ENV/bin/activate + +#envsubst < ${MACHINE_PATH}/dotfiles/ssh/config.template > ~/.ssh/config + +#export PATH=~/.npm-global/bin:$PATH + + diff --git a/usr/home/.config/qtile/config.py b/usr/home/.config/qtile/config.py new file mode 100644 index 0000000..5abfab1 --- /dev/null +++ b/usr/home/.config/qtile/config.py @@ -0,0 +1,237 @@ +# Copyright (c) 2010 Aldo Cortesi +# Copyright (c) 2010, 2014 dequis +# Copyright (c) 2012 Randall Ma +# Copyright (c) 2012-2014 Tycho Andersen +# Copyright (c) 2012 Craig Barnes +# Copyright (c) 2013 horsik +# Copyright (c) 2013 Tao Sauvage +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import os + +import libqtile.resources +from libqtile import bar, layout, qtile, widget +from libqtile.config import Click, Drag, Group, Key, Match, Screen +from libqtile.lazy import lazy +from libqtile.utils import guess_terminal + +mod = "mod4" +terminal = guess_terminal() + +keys = [ + Key([mod], "h", lazy.layout.left(), desc="Move focus to left"), + Key([mod], "l", lazy.layout.right(), desc="Move focus to right"), + Key([mod], "j", lazy.layout.down(), desc="Move focus down"), + Key([mod], "k", lazy.layout.up(), desc="Move focus up"), + Key([mod, "shift"], "h", lazy.layout.shuffle_left(), desc="Move window to the left"), + Key([mod, "shift"], "l", lazy.layout.shuffle_right(), desc="Move window to the right"), + Key([mod, "shift"], "j", lazy.layout.shuffle_down(), desc="Move window down"), + Key([mod, "shift"], "k", lazy.layout.shuffle_up(), desc="Move window up"), + Key([mod, "control"], "h", lazy.layout.grow_left(), desc="Grow window to the left"), + Key([mod, "control"], "l", lazy.layout.grow_right(), desc="Grow window to the right"), + Key([mod, "control"], "j", lazy.layout.grow_down(), desc="Grow window down"), + Key([mod, "control"], "k", lazy.layout.grow_up(), desc="Grow window up"), + Key([mod], "n", lazy.layout.normalize(), desc="Reset all window sizes"), + # Toggle between split and unsplit sides of stack. + # Split = all windows displayed + # Unsplit = 1 window displayed, like Max layout, but still with + # multiple stack panes + Key( + [mod, "shift"], + "Return", + lazy.layout.toggle_split(), + desc="Toggle between split and unsplit sides of stack", + ), + Key([mod], "Return", lazy.spawn(terminal), desc="Launch terminal"), + # Toggle between different layouts as defined below + Key([mod], "Tab", lazy.next_layout(), desc="Toggle between layouts"), + Key([mod], "w", lazy.window.kill(), desc="Kill focused window"), + Key( + [mod], + "f", + lazy.window.toggle_fullscreen(), + desc="Toggle fullscreen on the focused window", + ), + Key([mod], "t", lazy.window.toggle_floating(), desc="Toggle floating on the focused window"), + Key([mod, "control"], "r", lazy.reload_config(), desc="Reload the config"), + Key([mod, "control"], "q", lazy.shutdown(), desc="Shutdown Qtile"), + Key([mod], "r", lazy.spawncmd(), desc="Spawn a command using a prompt widget"), + Key([], "XF86AudioRaiseVolume", lazy.widget["vol"].increase_vol()), + Key([], "XF86AudioLowerVolume", lazy.widget["vol"].decrease_vol()), + Key([], "XF86AudioMute", lazy.widget["vol"].mute()), + +] + +# Add key bindings to switch VTs in Wayland. +# We can't check qtile.core.name in default config as it is loaded before qtile is started +# We therefore defer the check until the key binding is run by using .when(func=...) +for vt in range(1, 8): + keys.append( + Key( + ["control", "mod1"], + f"f{vt}", + lazy.core.change_vt(vt).when(func=lambda: qtile.core.name == "wayland"), + desc=f"Switch to VT{vt}", + ) + ) + +groups = [Group(i) for i in "123456789"] + +for i in groups: + keys.extend( + [ + # mod + group number = switch to group + Key( + [mod], + i.name, + lazy.group[i.name].toscreen(), + desc=f"Switch to group {i.name}", + ), + # mod + shift + group number = switch to & move focused window to group + Key( + [mod, "shift"], + i.name, + lazy.window.togroup(i.name, switch_group=True), + desc=f"Switch to & move focused window to group {i.name}", + ), + # Or, use below if you prefer not to switch to that group. + # # mod + shift + group number = move focused window to group + # Key([mod, "shift"], i.name, lazy.window.togroup(i.name), + # desc="move focused window to group {}".format(i.name)), + ] + ) + +layouts = [ + layout.Columns(border_focus_stack=["#d75f5f", "#8f3d3d"], border_width=4), + layout.Max(), + # Try more layouts by unleashing below layouts. + # layout.Stack(num_stacks=2), + # layout.Bsp(), + # layout.Matrix(), + # layout.MonadTall(), + # layout.MonadWide(), + # layout.RatioTile(), + # layout.Tile(), + # layout.TreeTab(), + # layout.VerticalTile(), + # layout.Zoomy(), +] + +widget_defaults = dict( + font="sans", + fontsize=9, + padding=3, +) +extension_defaults = widget_defaults.copy() + +logo = os.path.join(os.path.dirname(libqtile.resources.__file__), "~/.config/qtile/enso.png") + +def my_bar(): + return bar.Bar( + [ + widget.CurrentLayout(), + widget.GroupBox(), + widget.Prompt(), + widget.WindowName(), + widget.Chord( + chords_colors={ + "launch": ("#ff0000", "#ffffff"), + }, + name_transform=lambda name: name.upper(), + ), + # widget.StatusNotifier(), + widget.Systray(), + widget.Clock(format="%Y-%m-%d %a %I:%M %p"), + widget.QuickExit(), + ], + 24, + ) + +screens = [ + Screen( + background="#000000", + wallpaper=logo, + wallpaper_mode="center", + bottom=my_bar() +# x=1600,y=0 +# width=1920, height=1080 + ), + Screen = [ + bottom=my_bar() + background="#000000", + wallpaper=logo, + wallpaper_mode="center", +# x=0,y=0 +# width=1600, height=900 + ] +] + +# Drag floating layouts. +mouse = [ + Drag([mod], "Button1", lazy.window.set_position_floating(), start=lazy.window.get_position()), + Drag([mod], "Button3", lazy.window.set_size_floating(), start=lazy.window.get_size()), + Click([mod], "Button2", lazy.window.bring_to_front()), +] + +dgroups_key_binder = None +dgroups_app_rules = [] # type: list +follow_mouse_focus = True +bring_front_click = False +floats_kept_above = True +cursor_warp = False +floating_layout = layout.Floating( + float_rules=[ + # Run the utility of `xprop` to see the wm class and name of an X client. + *layout.Floating.default_float_rules, + Match(wm_class="confirmreset"), # gitk + Match(wm_class="makebranch"), # gitk + Match(wm_class="maketag"), # gitk + Match(wm_class="ssh-askpass"), # ssh-askpass + Match(title="branchdialog"), # gitk + Match(title="pinentry"), # GPG key password entry + ] +) +auto_fullscreen = True +focus_on_window_activation = "smart" +focus_previous_on_window_remove = False +reconfigure_screens = True + +# If things like steam games want to auto-minimize themselves when losing +# focus, should we respect this or not? +auto_minimize = True + +# When using the Wayland backend, this can be used to configure input devices. +wl_input_rules = None + +# xcursor theme (string or None) and size (integer) for Wayland backend +wl_xcursor_theme = None +wl_xcursor_size = 24 + +# XXX: Gasp! We're lying here. In fact, nobody really uses or cares about this +# string besides java UI toolkits; you can see several discussions on the +# mailing lists, GitHub issues, and other WM documentation that suggest setting +# this string if your java app doesn't work correctly. We may as well just lie +# and say that we're a working one by default. +# +# We choose LG3D to maximize irony: it is a 3D non-reparenting WM written in +# java that happens to be on java's whitelist. +wmname = "LG3D" + + diff --git a/usr/home/.inputrc b/usr/home/.inputrc new file mode 100644 index 0000000..23ae84c --- /dev/null +++ b/usr/home/.inputrc @@ -0,0 +1,25 @@ +set editing-mode vi +"\e[A": history-search-backward +"\e[B": history-search-forward + + +# For vi command mode +set keymap vi-command +"\e[A": history-search-backward +"\e[B": history-search-forward +"\eOA": history-search-backward +"\eOB": history-search-forward + +# For vi insert mode +set keymap vi-insert +"\e[A": history-search-backward +"\e[B": history-search-forward +"\eOA": history-search-backward +"\eOB": history-search-forward + +# Other settings +set completion-ignore-case on +set show-all-if-ambiguous on +set bell-style none +set match-hidden-files off + diff --git a/usr/home/.profile b/usr/home/.profile new file mode 100644 index 0000000..a7c050f --- /dev/null +++ b/usr/home/.profile @@ -0,0 +1 @@ +source /home/.profile diff --git a/usr/home/.vim/.netrwhist b/usr/home/.vim/.netrwhist new file mode 100644 index 0000000..d888493 --- /dev/null +++ b/usr/home/.vim/.netrwhist @@ -0,0 +1,9 @@ +let g:netrw_dirhistmax =10 +let g:netrw_dirhistcnt =7 +let g:netrw_dirhist_7='/home/archi/machine/networking' +let g:netrw_dirhist_6='/home/k/bs/shy-ni/haikus' +let g:netrw_dirhist_5='/home/k/bs/shy-ni/scenes' +let g:netrw_dirhist_4='/home/k/bs/shy-ni' +let g:netrw_dirhist_3='/home/k/bs/shy-ni/haikus' +let g:netrw_dirhist_2='/home/k/bs/shy-ni' +let g:netrw_dirhist_1='/home/k/machine/networking' diff --git a/usr/home/.vim/templates/template.c b/usr/home/.vim/templates/template.c new file mode 100644 index 0000000..e809fcf --- /dev/null +++ b/usr/home/.vim/templates/template.c @@ -0,0 +1,19 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* template.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: nidionis +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/09/04 16:20:59 by nidionis #+# #+# */ +/* Updated: 2024/09/05 14:15:32 by nidionis ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include + +int main(int argc, char **argv) +{ + return (0); +} diff --git a/usr/home/.vim/templates/template.h b/usr/home/.vim/templates/template.h new file mode 100644 index 0000000..e69de29 diff --git a/usr/home/.vim/templates/template.my_aliases b/usr/home/.vim/templates/template.my_aliases new file mode 100644 index 0000000..c5db6d6 --- /dev/null +++ b/usr/home/.vim/templates/template.my_aliases @@ -0,0 +1,25 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then + echo "Usage: $0 arg1 [arg2] [arg3]" + exit 1 +fi + +# interactive session check +if [ -t 0 ]; then + echo -n "Delete existing output files? [y/N]: " + read ans + case "$ans" in + y|Y) rm -f *.school ;; + *) echo "Aborted"; exit 0 ;; + esac +fi + +# process input file +while IFS= read -r line; do + new_f="${line%.*}.school" + f > "$new_f" +done < "$FILE" + +exit 0 + diff --git a/usr/home/.vim/templates/template.py b/usr/home/.vim/templates/template.py new file mode 100644 index 0000000..b13daf7 --- /dev/null +++ b/usr/home/.vim/templates/template.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python + +#!/usr/bin/env python3 +import argparse + +def parse_args(): + parser = argparse.ArgumentParser( + description="Template script using argparse" + ) + parser.add_argument( + "-i", "--input", + type=str, + help="Input file path", + required=True + ) + parser.add_argument( + "-o", "--output", + type=str, + help="Output file path", + required=False + ) + parser.add_argument( + "-v", "--verbose", + action="store_true", + help="Enable verbose mode" + ) + parser.add_argument( + "--mode", + choices=["fast", "slow"], + default="fast", + help="Choose mode of operation" + ) + return parser.parse_args() + +def main(): + args = parse_args() + + if args.verbose: + print("[INFO] Verbose mode is on") + print(f"[INFO] Input file: {args.input}") + print(f"[INFO] Output file: {args.output or 'stdout'}") + print(f"[INFO] Mode selected: {args.mode}") + + # Example processing + with open(args.input, 'r') as f: + data = f.read() + + result = data.upper() if args.mode == "fast" else data.lower() + + if args.output: + with open(args.output, 'w') as f: + f.write(result) + else: + print(result) + +if __name__ == "__main__": + main() + diff --git a/usr/home/.vim/templates/template.sh b/usr/home/.vim/templates/template.sh new file mode 100644 index 0000000..c5db6d6 --- /dev/null +++ b/usr/home/.vim/templates/template.sh @@ -0,0 +1,25 @@ +#!/usr/bin/bash + +if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then + echo "Usage: $0 arg1 [arg2] [arg3]" + exit 1 +fi + +# interactive session check +if [ -t 0 ]; then + echo -n "Delete existing output files? [y/N]: " + read ans + case "$ans" in + y|Y) rm -f *.school ;; + *) echo "Aborted"; exit 0 ;; + esac +fi + +# process input file +while IFS= read -r line; do + new_f="${line%.*}.school" + f > "$new_f" +done < "$FILE" + +exit 0 + diff --git a/usr/home/.vim/templates/template.yaml b/usr/home/.vim/templates/template.yaml new file mode 100644 index 0000000..efbae26 --- /dev/null +++ b/usr/home/.vim/templates/template.yaml @@ -0,0 +1,12 @@ +services: + web: + build: . + ports: + - "8000:5000" + develop: + watch: + - action: sync + path: . + target: /code + redis: + image: "redis:alpine" diff --git a/usr/home/.vimrc b/usr/home/.vimrc new file mode 100644 index 0000000..4b06189 --- /dev/null +++ b/usr/home/.vimrc @@ -0,0 +1,104 @@ +" https://www.freecodecamp.org/news/vimrc-configuration-guide-customize-your-vim-editor/ + +" Disable compatibility with vi which can cause unexpected issues. +set nocompatible + +" Enable type file detection. Vim will be able to try to detect the type of file is use. +filetype on + +" Enable plugins and load plugin for the detected file type. +filetype plugin on + +" Load an indent file for the detected file type. +filetype indent on + +" Turn syntax highlighting on. +syntax on + +" Add numbers to the file. +set number + +" Highlight cursor line underneath the cursor horizontally. +"set cursorline + +" Highlight cursor line underneath the cursor vertically. +"set cursorcolumn + +" Set shift width to 4 spaces. +set shiftwidth=4 + +" Set tab width to 4 columns. +set tabstop=4 + +" Use space characters instead of tabs. +"set expandtab + +" Do not save backup files. +" set nobackup +set backupdir=/tmp + +" Do not let cursor scroll below or above N number of lines when scrolling. +set scrolloff=10 + +" Do not wrap lines. Allow long lines to extend as far as the line goes. +"set nowrap + +" While searching though a file incrementally highlight matching characters as you type. +set incsearch + +" Ignore capital letters during search. +set ignorecase + +" Override the ignorecase option if searching for capital letters. +" This will allow you to search specifically for capital letters. + +set smartcase + +" Show partial command you type in the last line of the screen. +set showcmd + +" Show the mode you are on the last line. +"set showmode + +" Show matching words during a search. +set showmatch + +" Use highlighting when doing a search. +set hlsearch + +" Set the commands to save in history default number is 20. +set history=1000 + +" Enable auto completion menu after pressing TAB. +set wildmenu + +" Make wildmenu behave like similar to Bash completion. +"set wildmode=list:longest + +" There are certain files that we would never want to edit with Vim. +" Wildmenu will ignore files with these extensions. +set wildignore=*.docx,*.jpg,*.png,*.gif,*.pdf,*.pyc,*.exe,*.flv,*.img,*.xlsx + + +" skeletons +autocmd BufNewFile *.sh 0r ./.vim/templates/template.sh +autocmd BufNewFile *.py 0r ./.vim/templates/template.py +autocmd BufNewFile *.c 0r ./.vim/templates/template.c + +set mouse=a + +inoremap {{ {}O +inoremap {;{ ;}O + +:nnoremap @q + +set rnu + +set directory=/tmp + +colorscheme koehler + +set tags=./tags;,tags; + +syntax on +set tags=./tags;/ diff --git a/usr/lib/systemd/system/nftables.service b/usr/lib/systemd/system/nftables.service new file mode 100644 index 0000000..50a0d7a --- /dev/null +++ b/usr/lib/systemd/system/nftables.service @@ -0,0 +1,15 @@ +#to past in /usr/lib/systemd/system/nftables.service +#RemainAfterExit=yes added +[Unit] +Description=Netfilter Tables +Documentation=man:nft(8) +Wants=network-pre.target +Before=network-pre.target + +[Service] +Type=oneshot +ExecStart=/usr/bin/nft -f /etc/nftables.conf +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/usr/sbin/alpine-qemu-install b/usr/sbin/alpine-qemu-install new file mode 100755 index 0000000..8d98b34 --- /dev/null +++ b/usr/sbin/alpine-qemu-install @@ -0,0 +1,63 @@ +#!/bin/bash +set -eux + +ISO_URL="https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/x86_64/alpine-virt-3.22.2-x86_64.iso" + +# from vm to make a shared folder +if [ $# -lt 1 ] ; then + echo """ + ISO=${1:-$(basename $ISO_URL)} + IMG=${2:-disc_alpine.qcow2} + SIZE=${3:-16G} + RAM=${4:-2G} + CPUS=${5:-2} + SHARE=${6:-$PWD/share} + """ + echo "cheat sheet: mount -t 9p -o trans=virtio hostshare /mnt" +fi + +# --- Configurable defaults --- +ISO=${1:-$(basename $ISO_URL)} +IMG=${2:-disc_alpine.qcow2} +SIZE=${3:-16G} +RAM=${4:-2G} +CPUS=${5:-2} +SHARE=${6:-$PWD/share} + +# --- Setup --- +mkdir -p "$SHARE" +echo "iso = $ISO" +[ -f "$ISO" ] || wget "$ISO_URL" +[ -f "$IMG" ] || qemu-img create -o nocow=on -f qcow2 "$IMG" "$SIZE" + +# --- Optional install script --- +# Drop any file named install.sh in ./share to execute it inside the VM later: +# e.g. `bash /mnt/share/install.sh` after mounting + + + +qemu-system-x86_64 \ + -m $RAM \ + -boot once=d \ + -cdrom $ISO \ + -drive file=$IMG \ + -device virtio-vga \ + -enable-kvm \ + -display default,show-cursor=on \ + -nic user,hostfwd=tcp::2222-:22 \ + -virtfs local,id=share,path="$SHARE",security_model=none,mount_tag=hostshare + +## --- Run QEMU with graphics + shared folder --- +#qemu-system-x86_64 \ +# -enable-kvm \ +# -m "$RAM" \ +# -cpu host \ +# -smp "$CPUS" \ +# -boot d \ +# -cdrom "$ISO" \ +# -drive file="$IMG",format=qcow2 \ +# -device virtio-vga \ +# -display default,show-cursor=on \ +# -nic user,hostfwd=tcp::2222-:22 \ +# -virtfs local,id=share,path="$SHARE",security_model=none,mount_tag=hostshare + diff --git a/usr/sbin/arch-qemu-install b/usr/sbin/arch-qemu-install new file mode 100755 index 0000000..a1b7ba3 --- /dev/null +++ b/usr/sbin/arch-qemu-install @@ -0,0 +1,39 @@ +#!/bin/bash +set -eux + +# from vm to make a shared folder +echo "cheat sheet: mount -t 9p -o trans=virtio hostshare /mnt" + +# --- Configurable defaults --- +ISO_URL="https://mirror.arizona.edu/archlinux/iso/latest/archlinux-x86_64.iso" +ISO=${1:-$(basename $ISO_URL)} +IMG=${2:-disk_qemu.qcow2} +SIZE=${3:-16G} +RAM=${4:-2G} +CPUS=${5:-2} +SHARE=${6:-$PWD/share} + +# --- Setup --- +mkdir -p "$SHARE" +echo "iso = $ISO" +[ -f "$ISO" ] || wget "$ISO_URL" +[ -f "$IMG" ] || qemu-img create -o nocow=on -f qcow2 "$IMG" "$SIZE" + +# --- Optional install script --- +# Drop any file named install.sh in ./share to execute it inside the VM later: +# e.g. `bash /mnt/share/install.sh` after mounting + +# --- Run QEMU with graphics + shared folder --- +qemu-system-x86_64 \ + -enable-kvm \ + -m "$RAM" \ + -cpu host \ + -smp "$CPUS" \ + -boot d \ + -cdrom "$ISO" \ + -drive file="$IMG",format=qcow2 \ + -device virtio-vga \ + -display default,show-cursor=on \ + -nic user,hostfwd=tcp::2222-:22 \ + -virtfs local,id=share,path="$SHARE",security_model=none,mount_tag=hostshare + diff --git a/usr/sbin/basha b/usr/sbin/basha new file mode 100755 index 0000000..3213627 --- /dev/null +++ b/usr/sbin/basha @@ -0,0 +1,28 @@ +#!/usr/bin/bash + + +if [ "$#" -lt 1 ] || [ "$#" -gt 1 ]; then + echo "Usage: $0 alias" + exit 1 +fi + + +F=$(which "$1") + +if [ ! -f "$F" ]; then + F="$BIN_DIR/$1" + cp $MACHINE_DIR/usr/home/.vim/templates/template.sh $F +fi +vim "$F" +chmod +x $F + +cd $BIN_DIR +git pull +gitaddcommit +git push +cd - + + + +exit 0 + diff --git a/usr/sbin/basha-sudo b/usr/sbin/basha-sudo new file mode 100755 index 0000000..44abf95 --- /dev/null +++ b/usr/sbin/basha-sudo @@ -0,0 +1,28 @@ +#!/usr/bin/bash + + +if [ "$#" -lt 1 ] || [ "$#" -gt 1 ]; then + echo "Usage: $0 alias" + exit 1 +fi + + +F=$(which "$1") + +if [ ! -f "$F" ]; then + F="$SBIN_DIR/$1" + cp $MACHINE_DIR/usr/home/.vim/templates/template.sh $F +fi +vim "$F" +chmod +x $F + +cd $SBIN_DIR +git pull +gitaddcommit +git push +cd - + + + +exit 0 + diff --git a/usr/sbin/blacklist b/usr/sbin/blacklist new file mode 100755 index 0000000..41dc3c1 --- /dev/null +++ b/usr/sbin/blacklist @@ -0,0 +1,6 @@ +#!/usr/bin/bash + +set -e + +vim $BLACKLIST +bash $NFT_RESET diff --git a/usr/sbin/brc b/usr/sbin/brc new file mode 100755 index 0000000..fb20401 --- /dev/null +++ b/usr/sbin/brc @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e + +MACHINE_DIR=${1:$MACHINE_DIR} +MACHINE_DIR=${MACHINE_DIR:-"/svr"} +F_NAME=".bashrc"; +cd "$MACHINE_DIR/usr/home"; +commit_if_modified "$F_NAME" +cp -f $F_NAME /home/$F_NAME; +cd - diff --git a/usr/sbin/cert-librewolf b/usr/sbin/cert-librewolf new file mode 100755 index 0000000..464142a --- /dev/null +++ b/usr/sbin/cert-librewolf @@ -0,0 +1,19 @@ +#!/usr/bin/bash + +mkdir certs +cd certs + +openssl genrsa -out ca.key 4096 + +openssl req -x509 -new -sha256 -days 356000 -nodes -subj "/CN=LibreWolf CA/" -key ca.key -out ca.crt + +openssl genrsa -out librewolf.key 2048 + +openssl req -new -key librewolf.key -out librewolf.csr -subj '/CN=librewolf.local' + +echo "subjectAltName = DNS:librewolf.local,IP:127.0.0.1" > librewolf.ext + +openssl x509 -req -in librewolf.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out librewolf.crt -days 365 -sha256 -extfile librewolf.ext + +cd - +cp -r certs /srv/appdata/librewolf/config/ diff --git a/usr/sbin/chroot-iso b/usr/sbin/chroot-iso new file mode 100755 index 0000000..ce5712a --- /dev/null +++ b/usr/sbin/chroot-iso @@ -0,0 +1,30 @@ +#!/usr/bin/bash + +if [ "$#" -ne 1 ] ; then + echo "Usage: $0 .iso" + exit 1 +fi + +ISO="$1" +WORKDIR=iso_edit +NEWISO=custom.iso + +mkdir -p "$WORKDIR" +mount -o loop "$ISO" "$WORKDIR" + +echo "[*] Enter chroot (bind mounts first)" +mount --bind /dev "$WORKDIR/dev" +mount --bind /sys "$WORKDIR/sys" +mount --bind /proc "$WORKDIR/proc" +chroot "$WORKDIR" /bin/bash + +echo """ +run: +post-chroot-iso +""" +# sudo umount "$WORKDIR"/{proc,sys,dev} +# genisoimage -o "$NEWISO" -V "CUSTOM" -R -J "$WORKDIR" +# note : from cdrkit package + +exit 0 + diff --git a/usr/sbin/commit_if_modified b/usr/sbin/commit_if_modified new file mode 100755 index 0000000..741ae45 --- /dev/null +++ b/usr/sbin/commit_if_modified @@ -0,0 +1,20 @@ +#!/bin/bash +commit_if_modified () +{ + local F_NAME=$1; + local DEL=$2; + #git pull; + vim + $F_NAME; + git add $F_NAME; + git commit + if [ $? -eq 0 ] ; then + echo -n "[no modifications]"; + if [ -n "$DEL" ]; then + rm $F_NAME; + echo -n " -> deleted"; + return 1; + fi; + fi; + return 0 +} +commit_if_modified "$@" diff --git a/usr/sbin/gitaddcommit b/usr/sbin/gitaddcommit new file mode 100755 index 0000000..70d4af5 --- /dev/null +++ b/usr/sbin/gitaddcommit @@ -0,0 +1,11 @@ +#!/bin/bash +gitaddcommit () +{ + gitadd; + if [ -n "$1" ]; then + git commit -m "$1"; + else + git commit; + fi +} +gitaddcommit "$@" diff --git a/usr/sbin/journalctl_prettyfy b/usr/sbin/journalctl_prettyfy new file mode 100755 index 0000000..354a736 --- /dev/null +++ b/usr/sbin/journalctl_prettyfy @@ -0,0 +1,20 @@ +#!/bin/bash +journalctl_prettyfy () +{ + SIZE=${1:-"100"}; + UNIQ_MIN=${2:-"1"}; + BOOT=${3:-"0"}; + local TMP="/tmp/journalctl_prettyf.tmp"; + _FILE=${4:-"$TMP"}; + CMD="sudo journalctl -b ${BOOT} | tail -n $SIZE"; + CMD_SORTED="${CMD} | cut -d\: -f 4- | sort | uniq -c | sort -n"; + rm -f "$TMP"; + append_cmd "$CMD" "$TMP"; + append_cmd "$CMD_SORTED" "$TMP"; + grep --color=auto -vE " +[0-${UNIQ_MIN}] " $TMP >> "$_FILE"; + if ! $#; then + cat $_FILE; + fi; + rm "$TMP" +} +journalctl_prettyfy "$@" diff --git a/usr/sbin/monte b/usr/sbin/monte new file mode 100755 index 0000000..ac71567 --- /dev/null +++ b/usr/sbin/monte @@ -0,0 +1,18 @@ +#!/usr/bin/bash + +#if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then +# echo "Usage: mount the last sdx in dmesg" +# exit 1 +#fi + +SDX=${1:-$(dmesg | tail -1 | grep -Eo "sd[^ ]")} +SDX1=${SDX}1 +MNT_PT=/mnt/$SDX1 + +mkdir -p $MNT_PT + +mount /dev/${SDX1} $MNT_PT +cd $MNT_PT + +exit 0 + diff --git a/usr/sbin/nft-list b/usr/sbin/nft-list new file mode 100755 index 0000000..e1f07d0 --- /dev/null +++ b/usr/sbin/nft-list @@ -0,0 +1,6 @@ +#!/usr/bin/bash + +sudo -E bash $NETWORK_DIR/nft_setup.sh + +exit 0 + diff --git a/usr/sbin/refresh_time b/usr/sbin/refresh_time new file mode 100755 index 0000000..0ec2d46 --- /dev/null +++ b/usr/sbin/refresh_time @@ -0,0 +1,4 @@ +#!/bin/bash + +export DATE=$(date +"%y%m%d"); +export TIME=$(date +"%T") diff --git a/usr/sbin/sudoadd b/usr/sbin/sudoadd new file mode 100755 index 0000000..752a2d2 --- /dev/null +++ b/usr/sbin/sudoadd @@ -0,0 +1,6 @@ +#!/usr/bin/bash + +USER=${1:-"presko"} +groupadd $MACHINE +useradd -k $HOMESKEL_DIR -m -G sudo,$MACHINE $1 +usermod -aG $MACHINE $USER diff --git a/usr/sbin/tcpd b/usr/sbin/tcpd new file mode 100755 index 0000000..de46b9b --- /dev/null +++ b/usr/sbin/tcpd @@ -0,0 +1,41 @@ +#!/usr/bin/bash + +DIR=${1:-"$LOG_CONN_DIR"} +SUB_DIR=${2:-$(date "+%y%m%d")} +DIR="$DIR/$SUB_DIR" +NAME=${2:-"dflt"} +NAME=$(echo $(date +"%y%m%d")-$(date +"%T").$NAME | sed "s/:/_/g") +FILE=$DIR/$NAME + +echo "File at $FILE" +if [ "$#" -lt 1 ] ; then + echo "usage $0 filename" + echo "File at $FILE" + exit 1 +fi + +mkdir -p $DIR + +echo "File at $FILE" + +#DEVICE=$(ip addr | grep -v DOWN | grep -E "^[0-9]" | awk -F':' '{print $2}' | grep -v lo) +#NB_DEVICES="$(echo ${DEVICE} | awk '{print NF}')" +# +#if [ $NB_DEVICES -lt "1" ] ; then +# echo no device +# echo $DEVICE +# exit 1 +#elif [ $NB_DEVICES -gt "1" ] ; then +# echo several devices, precise it using '$2': +# echo $DEVICE +# exit 1 +#fi + +echo 'DEVICE='$DEVICE +echo + +tcpdump -n | tee -a $FILE.log +tcpdump -w $FILE.pcap + +exit 1 + diff --git a/usr/sbin/usb-reset b/usr/sbin/usb-reset new file mode 100755 index 0000000..6f4ec19 --- /dev/null +++ b/usr/sbin/usb-reset @@ -0,0 +1,42 @@ +#!/usr/bin/bash + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 /dev/sdb" + exit 1 +fi + +#!/bin/sh +# partitionne /dev/sdb en une partition unique FAT32 montable Win/Linux + +dev=$1 + +# créer table de partition MBR et 1 partition FAT32 +fdisk "$dev" < 0 then + data = data:gsub("%s+", " ") + return ("port %d open — banner: %q"):format(port.number, data) + end + + return ("port %d open — no banner"):format(port.number) +end +