From 471bd4de87d7d7623caf255e1c0628c1e502d12f Mon Sep 17 00:00:00 2001 From: "Git Commiter for 96-fromsofia.net" <2a9-7cc@96-fromsofia.net> Date: Mon, 27 Feb 2023 00:21:12 +0000 Subject: [PATCH] First commit --- README.txt | 15 ++++ arch-install.sh | 135 ++++++++++++++++++++++++++++++++++ arch-lvm-install.sh | 174 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 324 insertions(+) create mode 100644 README.txt create mode 100644 arch-install.sh create mode 100644 arch-lvm-install.sh diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..75c2621 --- /dev/null +++ b/README.txt @@ -0,0 +1,15 @@ +DESCRIPTION: +I use archlinux and this is my automated deployment script. It will only go through the install process of wiki.archlinux.org including some of the "hardening" tutorials from the same domain. +There is a script to use standard MBR partitioning and a script to use LVM partitioning. +The script will also create 3 users - one to login (potrebitel); one to upgrade packages (devel); one to administer the systemem and escalate to root if needed; +Additionally the following packages will be installed and configured: +base base-devel linux-hardened linux-hardened-headers linux-firmware vim man-db man-pages texinfo bash-completion amd-ucode sudo grub apparmor firejail openssh lvm2 #<-- This is only installed in the LVM version. + +NOTE: +As it is usually the case with archlinux, this script will give you a "sane" configuration according to myself and my use cases.. +The script is not intended as a replacement to the installation guide in wiki.archlinux.org +Prior to use please review the *.sh files and understand the commands that are ran to ensure this works for you. + +AUTHOR: +96-fromsofia - 2A9-7CC@96-fromsofia.net || August 2021 + diff --git a/arch-install.sh b/arch-install.sh new file mode 100644 index 0000000..ea5fd72 --- /dev/null +++ b/arch-install.sh @@ -0,0 +1,135 @@ +#!/bin/bash + +# Vars +os_disk=/dev/sdX +swap_disk=/dev/sdX1 +root_disk=/dev/sdX2 +time_zone="" +hostname="" +vps_ip="" +vps_gw="" +vps_dns="" +potr_pass="openssl rand -base64 10" +dev_pass="openssl rand -base64 14" +adm_pass="openssl rand -base64 14" +root_pass="openssl rand -base64 100" +grub_pass="openssl rand -base64 8" +ssh_port=$(shuf -i 14206-65091 -n1) +ssh_file=/etc/ssh/sshd_config +fw_file=/etc/iptables/iptables.rules + +function osinstall { + # Ensure system clock is accurate + timedatectl set-ntp true + # Create FS layout + (echo o; echo n; echo ""; echo ""; echo ""; echo "+2G"; echo t; echo 82; echo n; echo ""; echo ""; echo ""; echo ""; echo w) | fdisk $os_disk + mkfs.ext4 $root_disk + mount $root_disk /mnt/ + mkswap $swap_disk + swapon $swap_disk + # Sort out mirrolist + yes | pacman -Sy pacman-contrib + cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist_back + rankmirrors -n 6 /etc/pacman.d/mirrorlist_back > /etc/pacman.d/mirrorlist + sync ; pacstrap /mnt base base-devel linux-hardened linux-hardened-headers linux-firmware vim man-db man-pages texinfo bash-completion amd-ucode sudo grub apparmor firejail openssh +} + +function ossetup { + # Copy FSTAB and chroot + genfstab -U /mnt >> /mnt/etc/fstab + arch-chroot /mnt/ << EOF + + # Fix time and locale + ln -sf /usr/share/zoneinfo/$time_zone /etc/localtime + hwclock --systohc + sed -i "s/#en_US.UTF-8/en_US.UTF-8/" /etc/locale.gen + locale-gen + echo "LANG=en_US.UTF-8" > /etc/locale.conf + + # Set up network + echo $hostname > /etc/hostname + echo -e "127.0.0.1 localhost\n::1 localhost\n127.0.1.1 katya.localdomain katya" > /etc/hosts + for i in $vps_dns ; do echo -e "nameserver $i" >> /etc/resolv.conf ; done + systemctl enable systemd-networkd + systemctl enable systemd-resolved + echo -e "[Match]\nName=enp0s3\n\n[Network]\nAddress=$vps_ip\nGateway=$vps_gw\nDNS=$vps_dns" > /etc/systemd/network/20-wired.network + + # Create users, tighten pam and sudo + useradd -g users -s /bin/bash -m potrebitel + useradd -g users -s /bin/bash -m devel + useradd -g users -s /bin/bash -m admin + (echo $potr_pass; echo $potr_pass) | passwd potrebitel + (echo $dev_pass; echo $dev_pass) | passwd devel + (echo $adm_pass; echo $adm_pass) | passwd admin + sed -i 's/#auth required pam_wheel.so use_uid/auth required pam_wheel.so use_uid/' /etc/pam.d/{su,su-l} + groupadd -r ssh ; + for g in power ssh; do gpasswd -a potrebitel \$g ; done + for g in network power storage; do gpasswd -a admin \$g ; done + chown -R devel:root /etc/{vim,wireguard,unbound,ssh,bash} + sed -i 's/root ALL=(ALL) ALL/# root ALL=(ALL) ALL/' /etc/sudoers + sed -i 's/@includedir/#@includedir/' /etc/sudoers + echo -e 'Defaults env_reset\nDefaults editor=/usr/bin/rvim\nDefaults passwd_timeout=0\nDefaults timestamp_timeout=15\nDefaults insults\nCmnd_Alias POWER = /usr/bin/shutdown -h now, /usr/bin/halt, /usr/bin/poweroff, /usr/bin/reboot\nCmnd_Alias STORAGE = /usr/bin/mount -o nosuid\,nodev\,noexec, /usr/bin/umount\nCmnd_Alias SYSTEMD = /usr/bin/journalctl, /usr/bin/systemctl\nCmnd_Alias KILL = /usr/bin/kill, /usr/bin/killall\nCmnd_Alias PKGMAN = /usr/bin/pacman\nCmnd_Alias NETWORK = /usr/bin/systemctl systemd-networkd, /usr/bin/systemctl systemd-resolved, /usr/bin/wg, /usr/bin/wg-quick\nCmnd_Alias FIREWALL = /usr/bin/iptables, /usr/bin/ip6tables\nCmnd_Alias SHELL = /usr/bin/zsh, /usr/bin/bash\n%power ALL = (root) NOPASSWD: POWER\n%network ALL = (root) NETWORK\n%storage ALL = (root) STORAGE\nroot ALL = (ALL) ALL\nadmin ALL = (root) SYSTEMD, KILL, FIREWALL, STORAGE, /usr/bin/bash\ndevel ALL = (root) PKGMAN\npotrebitel ALL = (devel) SHELL, (admin) SHELL\n@includedir /etc/sudoers.d' >> /etc/sudoers + chown -c root:root /etc/sudoers + chmod -c 0440 /etc/sudoers + echo "alias sudo='sudo -v; sudo '" >> /etc/bash.bashrc + + # Iptables + cp $fw_file /root/.iptables_bk + systemctl enable iptables + iptables -F + iptables -A INPUT -i lo -j ACCEPT + iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT + iptables -A INPUT -p tcp --dport $ssh_port -j ACCEPT -m comment --comment "SSH ACCESS" + iptables -A INPUT -p tcp --dport $ssh_port -m state --state NEW -m recent --set --name ssh --rsource -m comment --comment "SSH ACCESS" + iptables -I INPUT -p tcp --dport $ssh_port -m state --state NEW -m recent ! --rcheck --seconds 90 --hitcount 3 --name ssh --rsource -j ACCEPT -m comment --comment "SSH ACCESS" + iptables -P INPUT DROP + iptables -P FORWARD DROP + iptables -P OUTPUT ACCEPT + iptables-save > $fw_file + + # SSH + sed -i "s/#Port\ 22/Port\ $ssh_port/" $ssh_file + sed -i 's/#AddressFamily\ any/AddressFamily\ inet/' $ssh_file + sed -i 's/PermitRootLogin\ yes/PermitRootLogin\ no/' $ssh_file + echo -e "AllowUsers potrebitel\nDenyUsers root devel admin\nProtocol 2" >> $ssh_file + systemctl enable sshd + + # Misc hardening + chmod 700 /boot /etc/{iptables,ssh,bash.bashrc} + sed -i "s/umask 022/umask 0077/" /etc/profile + echo -e "-:root:ALL\n+:admin:LOCAL\n-:admin:ALL\n-:devel:ALL\n+:potrebitel:ALL" >> /etc/security/access.conf + systemctl enable apparmor.service + echo -e 'TMOUT="$(( 60*10 ))";\n[ -z "$DISPLAY" ] && export TMOUT;\ncase $( /usr/bin/tty ) in\n /dev/tty[0-9]*) export TMOUT;;\nesac\n' > /etc/profile.d/shell-timeout.sh + echo -e 'net.ipv4.tcp_rfc1337 = 1\nnet.ipv4.conf.default.rp_filter = 1\nnet.ipv4.conf.all.rp_filter = 1\nnet.ipv6.conf.all.disable= = 1' > /etc/sysctl.d/99-sysctl.conf + + # Install GRUB + grub-install --target=i386-pc $os_disk + (echo $grub_pass; echo $grub_pass) | grub-mkpasswd-pbkdf2 | tail -1 | rev | awk '{print \$1}' | rev > /root/.grub_passphrase.txt + chown root:root /etc/grub.d/40_custom + chmod 0700 /etc/grub.d/40_custom + echo -e "set superusers=\"username\"\npassword_pbkdf2 username \$(cat /root/.grub_passphrase.txt)" >> /etc/grub.d/40_custom + sed -i 's/CLASS="--class gnu-linux --class gnu --class os"/CLASS="--class gnu-linux --class gnu --class os --unrestricted"/' /etc/grub.d/10_linux + sed -i 's/GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="lsm=lockdown,yama,apparmor,bpf,lockdown=confidentiality,ipv6.disable=1"/' /etc/default/grub + mkinitcpio -P + grub-mkconfig -o /boot/grub/grub.cfg + rm -rf /root/.grub_passphrase.txt +EOF +} + +osinstall +ossetup + +dialog --yesno "IP: $vps_ip\nSSH: $ssh_port\nPass: $potr_pass\nDev_Pass: $dev_pass\nAdm_Pass: $adm_pass\nGRUB: $grub_pass\n\nWould you like to reboot the box?" 20 50 +ans=$? + +if [ $ans == "0" ] +then + umount -R /mnt + sleep 3 + sync + shutdown -h now +else + echo "Goodbye! Dropping you to a shell now.." + exit +fi + diff --git a/arch-lvm-install.sh b/arch-lvm-install.sh new file mode 100644 index 0000000..a8b4abc --- /dev/null +++ b/arch-lvm-install.sh @@ -0,0 +1,174 @@ +#!/bin/bash + +# Vars +os_disk=/dev/sda +time_zone="" +hostname="" +vps_ip="" +vps_gw="" +vps_dns="" +potr_pass=$(openssl rand -base64 10) +dev_pass=$(openssl rand -base64 14) +adm_pass=$(openssl rand -base64 14) +root_pass=$(openssl rand -base64 100) +grub_pass=$(openssl rand -base64 8) +ssh_port=$(shuf -i 14206-65091 -n1) +ssh_file=/etc/ssh/sshd_config +fw_file=/etc/iptables/iptables.rules + +function osinstall { + # Ensure system clock is accurate + timedatectl set-ntp true + # Create FS layout + (echo o; echo n; echo ""; echo ""; echo ""; echo ""; echo t; echo 30; echo w) | fdisk $os_disk + yes | pvcreate $(echo $os_disk)1 + yes | vgcreate OS-volume $(echo $os_disk)1 + yes | lvcreate -L 4GB OS-volume -n swap + yes | lvcreate -L 3GB OS-volume -n root + yes | lvcreate -L 1GB OS-volume -n home + yes | lvcreate -L 1GB OS-volume -n tmp + yes | lvcreate -L 10GB OS-volume -n usr + yes | lvcreate -L 2GB OS-volume -n var + yes | lvcreate -L 2GB OS-volume -n var_log + yes | lvcreate -l 100%FREE OS-volume -n var_mail + modprobe dm_mod + vgscan + vgchange -ay + mkswap /dev/OS-volume/swap + swapon /dev/OS-volume/swap + mkfs.ext4 /dev/OS-volume/root + mkfs.ext4 /dev/OS-volume/home + mkfs.ext4 /dev/OS-volume/tmp + mkfs.ext4 /dev/OS-volume/usr + mkfs.ext4 /dev/OS-volume/var + mkfs.ext4 /dev/OS-volume/var_log + mkfs.ext4 /dev/OS-volume/var_mail + mount /dev/OS-volume/root /mnt + mkdir /mnt/home ; mount -o nodev,noexec,nosuid /dev/OS-volume/home /mnt/home + mkdir /mnt/tmp ; mount -o nodev,noexec,nosuid /dev/OS-volume/tmp /mnt/tmp + mkdir /mnt/usr ; mount -o nodev /dev/OS-volume/usr /mnt/usr + mkdir /mnt/var ; mount -o nodev,noexec,nosuid /dev/OS-volume/var /mnt/var + # Sort out mirrolist + yes | pacman -Sy pacman-contrib + cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist_back + rankmirrors -n 6 /etc/pacman.d/mirrorlist_back > /etc/pacman.d/mirrorlist + yes | pacman -Sy dialog + sync ; pacstrap /mnt base base-devel linux-hardened linux-hardened-headers linux-firmware vim man-db man-pages texinfo bash-completion amd-ucode sudo grub apparmor firejail openssh lvm2 +} + +function ossetup { + # Copy FSTAB and chroot + genfstab -U /mnt >> /mnt/etc/fstab + cd /mnt + mount -t proc /proc proc/ + mount -t sysfs /sys sys/ + mount -o bind /dev dev/ + mount -o bind /run run/ + chroot /mnt /bin/bash << EOF + + # Fix environment + source /etc/profile + source ~/.bashrc + + # Fix time and locale + ln -sf /usr/share/zoneinfo/$time_zone /etc/localtime + hwclock --systohc + sed -i "s/#en_US.UTF-8/en_US.UTF-8/" /etc/locale.gen + locale-gen + echo "LANG=en_US.UTF-8" > /etc/locale.conf + + # Set up network + echo $hostname > /etc/hostname + echo -e "127.0.0.1 localhost\n::1 localhost\n127.0.1.1 katya.localdomain katya" > /etc/hosts + for i in $vps_dns ; do echo -e "nameserver $i" >> /etc/resolv.conf ; done + systemctl enable systemd-networkd + systemctl enable systemd-resolved + echo -e "[Match]\nName=enp0s3\n\n[Network]\nAddress=$vps_ip\nGateway=$vps_gw\nDNS=$vps_dns" > /etc/systemd/network/20-wired.network + + # Create users, tighten pam and sudo + useradd -g users -s /bin/bash -m potrebitel + useradd -g users -s /bin/bash -m devel + useradd -g users -s /bin/bash -m admin + (echo $potr_pass; echo $potr_pass) | passwd potrebitel + (echo $dev_pass; echo $dev_pass) | passwd devel + (echo $adm_pass; echo $adm_pass) | passwd admin + sed -i 's/#auth required pam_wheel.so use_uid/auth required pam_wheel.so use_uid/' /etc/pam.d/{su,su-l} + groupadd -r ssh ; + for g in power ssh; do gpasswd -a potrebitel \$g ; done + for g in network power storage; do gpasswd -a admin \$g ; done + chown -R devel:root /etc/{vim*,ssh,bash*} + sed -i 's/root ALL=(ALL) ALL/# root ALL=(ALL) ALL/' /etc/sudoers + sed -i 's/@includedir/#@includedir/' /etc/sudoers + echo -e 'Defaults env_reset\nDefaults editor=/usr/bin/rvim\nDefaults passwd_timeout=0\nDefaults timestamp_timeout=15\nDefaults insults\nCmnd_Alias POWER = /usr/bin/shutdown -h now, /usr/bin/halt, /usr/bin/poweroff, /usr/bin/reboot\nCmnd_Alias STORAGE = /usr/bin/mount -o nosuid\,nodev\,noexec, /usr/bin/umount\nCmnd_Alias SYSTEMD = /usr/bin/journalctl, /usr/bin/systemctl\nCmnd_Alias KILL = /usr/bin/kill, /usr/bin/killall\nCmnd_Alias PKGMAN = /usr/bin/pacman\nCmnd_Alias NETWORK = /usr/bin/systemctl systemd-networkd, /usr/bin/systemctl systemd-resolved, /usr/bin/wg, /usr/bin/wg-quick\nCmnd_Alias FIREWALL = /usr/bin/iptables, /usr/bin/ip6tables\nCmnd_Alias SHELL = /usr/bin/zsh, /usr/bin/bash\n%power ALL = (root) NOPASSWD: POWER\n%network ALL = (root) NETWORK\n%storage ALL = (root) STORAGE\nroot ALL = (ALL) ALL\nadmin ALL = (root) SYSTEMD, KILL, FIREWALL, STORAGE, /usr/bin/bash\ndevel ALL = (root) PKGMAN\npotrebitel ALL = (devel) SHELL, (admin) SHELL\n@includedir /etc/sudoers.d' >> /etc/sudoers + chown -c root:root /etc/sudoers + chmod -c 0440 /etc/sudoers + echo "alias sudo='sudo -v; sudo '" >> /etc/bash.bashrc + + # Iptables + cp $fw_file /root/.iptables_bk + systemctl enable iptables + iptables -F + iptables -A INPUT -i lo -j ACCEPT + iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT + iptables -A INPUT -p tcp --dport $ssh_port -j ACCEPT -m comment --comment "SSH ACCESS" + iptables -A INPUT -p tcp --dport $ssh_port -m state --state NEW -m recent --set --name ssh --rsource -m comment --comment "SSH ACCESS" + iptables -I INPUT -p tcp --dport $ssh_port -m state --state NEW -m recent ! --rcheck --seconds 90 --hitcount 3 --name ssh --rsource -j ACCEPT -m comment --comment "SSH ACCESS" + iptables -P INPUT DROP + iptables -P FORWARD DROP + iptables -P OUTPUT ACCEPT + iptables-save > $fw_file + + # SSH + sed -i "s/#Port\ 22/Port\ $ssh_port/" $ssh_file + sed -i 's/#AddressFamily\ any/AddressFamily\ inet/' $ssh_file + sed -i 's/PermitRootLogin\ yes/PermitRootLogin\ no/' $ssh_file + echo -e "AllowUsers potrebitel\nDenyUsers root devel admin\nProtocol 2" >> $ssh_file + systemctl enable sshd + + # Misc hardening + chmod 700 /boot /etc/{iptables,ssh,bash.bashrc} + sed -i "s/umask 022/umask 0077/" /etc/profile + echo -e "-:root:ALL\n+:admin:LOCAL\n-:admin:ALL\n-:devel:ALL\n+:potrebitel:ALL" >> /etc/security/access.conf + systemctl enable apparmor.service + echo -e 'TMOUT="$(( 60*10 ))";\n[ -z "$DISPLAY" ] && export TMOUT;\ncase $( /usr/bin/tty ) in\n /dev/tty[0-9]*) export TMOUT;;\nesac\n' > /etc/profile.d/shell-timeout.sh + echo -e 'net.ipv4.tcp_rfc1337 = 1\nnet.ipv4.conf.default.rp_filter = 1\nnet.ipv4.conf.all.rp_filter = 1\nnet.ipv6.conf.all.disable= = 1' > /etc/sysctl.d/99-sysctl.conf + + # Install GRUB + sed -i 's/HOOKS=(base udev autodetect modconf block filesystems keyboard fsck)/HOOKS=(base systemd autodetect modconf block lvm2 filesystems keyboard fsck)/' /etc/mkinitcpio.conf + mkinitcpio -P + grub-install --target=i386-pc $os_disk + (echo $grub_pass; echo $grub_pass) | grub-mkpasswd-pbkdf2 | tail -1 | rev | awk '{print \$1}' | rev > /root/.grub_passphrase.txt + chown root:root /etc/grub.d/40_custom + chmod 0700 /etc/grub.d/40_custom + echo -e "set superusers=\"username\"\npassword_pbkdf2 username \$(cat /root/.grub_passphrase.txt)" >> /etc/grub.d/40_custom + sed -i 's/CLASS="--class gnu-linux --class gnu --class os"/CLASS="--class gnu-linux --class gnu --class os --unrestricted"/' /etc/grub.d/10_linux + sed -i 's/GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="lsm=lockdown,yama,apparmor,bpf,lockdown=confidentiality,ipv6.disable=1,root=\/dev\/OS-volume\/root"/' /etc/default/grub + sed -i 's/GRUB_PRELOAD_MODULES="part_gpt part_msdos"/GRUB_PRELOAD_MODULES="part_gpt part_msdos lvm"/' /etc/default/grub + grub-mkconfig -o /boot/grub/grub.cfg + rm -rf /root/.grub_passphrase.txt +EOF + cd / +} + +function osexit { + # Provide credentials and access info and ask if to reboot or exit script to shell + echo -e "IP: $vps_ip\nSSH: $ssh_port\nPass: $potr_pass\nDev_Pass: $dev_pass\nAdm_Pass: $adm_pass\nGRUB: $grub_pass\n\nWould you like to reboot the box?" >> /mnt/root/credentials.txt + dialog --yesno "$(cat /mnt/root/credentials.txt)\n\nCredentials and access info saved at: /mnt/root/credentials.txt\nWould you like to reboot the box?" 20 50 + ans=$? + # Based on answer given either reboot or drop to shell + if [ $ans == "0" ] + then + umount -R /mnt + sleep 3 + sync + shutdown -h now + else + echo "Goodbye! Dropping you to a shell now.." + exit + fi +} + +osinstall +ossetup +osexit +