Last active
April 24, 2025 00:30
-
-
Save jrcharney/d70f02d11f5e5fb0c10093fdd07a268d to your computer and use it in GitHub Desktop.
Interactive UFW setup script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # File: setup-ufw.sh | |
| # Created by: Jason Charney (https://github.com/jrcharney) | |
| # Date: 14 April 2025 | |
| # Info: Interactive Uncomplicated Firewall (ufw) setup script | |
| # ufw is not a replacement for iptables, but a front-end. It is certainly more pleasant to use. | |
| # NOTE: You MUST run this script as super user. Every Uncomplicated Firewall (ufw) command outside of this script starts with `sudo`. | |
| # Requirements: | |
| # - Make sure ufw and sshd is installed. | |
| # sudo pacman -S ufw # Or whatever package manager that you use. | |
| # - Make sure that systemctl has ufw enabled and started. | |
| # systemctl status ufw | |
| # - If it isn't do this command | |
| # sudo systemctl enable --now ufw | |
| # Usage: | |
| # 1. Tweak any variables in this script, like if you have a different subnet you are using. | |
| # 2. chmod +x setup-ufw.sh | |
| # 3. sudo ./setup-ufw.sh | |
| # TODO: Do we need to define rules for DNS (especially outgoing)? | |
| # TODO: Do we need to define rules for Mail servers? | |
| # NOTE: Avoid using `on any` in any of the rules. Use `from {subnet}`. | |
| # Colors | |
| RED="\x1b[0;31m" | |
| GREEN="\x1b[0;32m" | |
| YELLOW="\x1b[0;33m" | |
| NC="\x1b[0m" # No color (reset) | |
| # Exit on any error | |
| set -e | |
| # Super user check (You need to sudo or it won't go through!) | |
| if [[ $EUID -ne 0 ]]; then | |
| echo -e "${RED}ERROR:${NC} Super users only!" | |
| echo -e "This script must be run as root." | |
| echo -e "Please use sudo, switch to root, or contact the administrator." | |
| exit 1 | |
| fi | |
| # Check for UFW and SSHD | |
| software_sanity_check() { | |
| for pkg in ufw sshd; do | |
| command -v ${pkg} > /dev/null 2>&1 || { | |
| echo -e "${RED}ERROR:${NC} Required package ${YELLOW}'${pkg}'${NC} is not installed." >&2 | |
| exit 1 | |
| } | |
| echo -e "${YELLOW}'${pkg}'${NC} ${GREEN}found.${NC}" | |
| done | |
| } | |
| # Ensure UFW and SSHD are enabled and running | |
| service_sanity_check() { | |
| for svc in ufw sshd; do | |
| systemctl is-enabled ${svc} > /dev/null || { | |
| echo -e "${GREEN}Enabling${NC} ${YELLOW}${svc}${NC} ${GREEN}service...${NC}" | |
| systemctl enable ${svc} | |
| } | |
| systemctl is-active ${svc} > /dev/null || { | |
| echo -e "${GREEN}Starting${NC} ${YELLOW}${svc}${NC} ${GREEN}service...${NC}" | |
| systemctl start ${svc} | |
| } | |
| done | |
| } | |
| # TODO: Refine these CIDRv4 validations if you can. (because each section is supposed to be an number between 0 and 255) | |
| validate_cidr() { | |
| [[ $1 =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]+$ ]] | |
| } | |
| validate_cidr6() { | |
| [[ $1 =~ ^([a-fA-F0-9:]+)(/[0-9]+)?$ ]] | |
| } | |
| prompt_subnet_with_validation() { | |
| local prompt="$1" | |
| local default="$2" | |
| local validate_fn="$3" | |
| local attempts=0 | |
| local input | |
| while [ ${attempts} -lt 3 ]; do | |
| read -rp "${prompt} [${default}]: " input | |
| input="${input:-$default}" | |
| if "${validate_fn}" "${input}"; then | |
| echo "${input}" | |
| return 0 | |
| else | |
| echo -e "${RED}ERROR:${NC} Invalid format. Please try again." >&2 # stderr | |
| ((attempts++)) | |
| fi | |
| done | |
| echo -e "${RED}ERROR:${NC} Too many invalid attempts. Aborting." >&2 # stderr | |
| exit 1 | |
| } | |
| # TODO: might want to find another way to get the help information out of this function | |
| get_ip() { | |
| local ip_version="-4" | |
| local strip_subnet=false | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| -4 | --ipv4) | |
| ip_version="-4" | |
| shift | |
| ;; | |
| -6 | --ipv6) | |
| ip_version="-6" | |
| shift | |
| ;; | |
| -s | --strip-subnet) | |
| strip_subnet=true | |
| shift | |
| ;; | |
| # NOTE: Not sure why I put this here. Old habit, I guess. | |
| #-h|--help) | |
| # echo "Usage: get_ip [-4|--ipv4] [-6|--ipv6] [-s|--strip-subnet]" | |
| # return 0 | |
| # ;; | |
| *) | |
| echo -e "${RED}ERROR:${NC} Unknown option ${YELLOW}$1${NC}." >&2 # stderr | |
| return 1 | |
| ;; | |
| esac | |
| done | |
| local ip_address | |
| if [[ ${ip_version##*-} == 4 ]]; then | |
| ip_address=$(ip ${ip_version} addr show scope global | awk '/inet / {print $2}') # | cut -d/ -f1 | |
| else | |
| ip_address=$(ip ${ip_version} addr show scope global | awk '/inet6 / {print $2}') # | cut -d/ -f1 | |
| fi | |
| if [[ -z ${ip_address} ]]; then | |
| echo -e "${RED}ERROR:${NC} No IP address found for IPv${ip_version##*-}." >&2 # stderr | |
| return 0 | |
| fi | |
| # This does our `| cut -d/ -f1` that we could have done earlier. | |
| [[ ${strip_subnet} == true ]] && echo "${ip_address%%/*}" || echo "${ip_address}" | |
| } | |
| # NOTE: I only plan on using this function ONCE. | |
| get_all_ips() { | |
| local ipv4=$(get_ip -4 -s 2> /dev/null) | |
| local ipv6=$(get_ip -6 -s 2> /dev/null) | |
| [[ -n ${ipv4} ]] && echo -n "${ipv4}" | |
| [[ -n ${ipv4} && -n ${ipv6} ]] && echo -n " or " | |
| [[ -n ${ipv6} ]] && echo -n "${ipv6}" | |
| } | |
| # TODO: Just for fun, have it show the subnet mask. Like when you enter `/24` it should return `255.255.255.0` | |
| # TODO: Make another version of this method that allows for more information. | |
| # TODO: Make another version of this method that says yes to all questions. | |
| # TODO: Make another version of this method that says no to all questions. | |
| # TODO: Make another version of this method that aborts the program. | |
| # TODO: I though I wrote a script that did the count increase and the while test together? | |
| prompt_yn() { | |
| local prompt="$1" | |
| local default="${2:-Y}" # Default to 'Y' if not provided | |
| local attempts=0 | |
| # Normalize default to lowercase y/n for comparison | |
| local default_lower=$(echo "$default" | tr '[:upper:]' '[:lower:]') | |
| local default_prompt=$([[ $default_lower == "y" ]] && echo "[Y/n]" || echo "[y/N]") | |
| while [ ${attempts} -lt 3 ]; do | |
| read -rp "${prompt} ${default_prompt}: " yn | |
| yn="${yn:-$default}" # Use default if input is empty | |
| case ${yn,,} in # Lowercase comparison | |
| [Yy]*) return 0 ;; | |
| [Nn]*) return 1 ;; | |
| *) echo "Please answer yes or no" >&2 ;; | |
| esac | |
| ((attempts++)) | |
| done | |
| echo -e "${RED}ERROR:${NC} Too many invalid attempts. Aborting." >&2 | |
| exit 1 | |
| } | |
| echo -e "${GREEN}Let's check to see if we have our software.${NC}" | |
| software_sanity_check | |
| echo -e "${GREEN}It looks like we have everything.${NC}" | |
| echo -e "${GREEN}Let's look up our IP address(es)${NC}" | |
| ipv4=$(get_ip -4 -s 2> /dev/null) | |
| ipv6=$(get_ip -6 -s 2> /dev/null) | |
| echo -n "IPv4: " | |
| [[ -n ${ipv4} ]] && echo -e "${GREEN}$ipv4${NC}" || echo -e "${RED}N/A${NC}" | |
| echo -n "IPv6: " | |
| [[ -n ${ipv6} ]] && echo -e "${GREEN}$ipv6${NC}" || echo -e "${RED}N/A${NC}" | |
| # Let's not run this program if there is no internet. | |
| if [[ -z $ipv4 && -z $ipv6 ]]; then | |
| echo "${RED}ERROR:${NC} No IP address found (IPv4 or IPv6). Come back when you have IP addresses." >&2 | |
| exit 1 | |
| fi | |
| echo -e "${GREEN}But first, a few of questions.${NC}" | |
| # Define your local subnet | |
| #read -p "Enter LAN IPv4 subnet [default: 192.168.0.0/24]: " LAN_SUBNET_v4 | |
| #LAN_SUBNET_v4=${LAN_SUBNET_v4:-192.168.0.0/24} | |
| #read -p "Enter LAN IPv6 subnet [default: fe80::/10]: " LAN_SUBNET_v6 | |
| #LAN_SUBNET_v6=${LAN_SUBNET_v6:-fe80::/10} | |
| # I love how this is done! Yes, that is a callback at the end! | |
| LAN_SUBNET_v4=$(prompt_subnet_with_validation "Enter your LAN subnet (IPv4 CIDR)" "192.168.0.0/24" validate_cidr) | |
| LAN_SUBNET_v6=$(prompt_subnet_with_validation "Enter your LAN subnet (IPv6)" "fe80::/10" validate_cidr6) | |
| # Method: rule | |
| # Info: A function for writing the more common rules | |
| # Creating a standardized set of rules | |
| # NOTE: This function MUST be defined after the LAN_SUBNET_v4 and LAN_SUBNET_v6 variables are defined! | |
| # Although ufw does have shorthand methods for writing rules, I wanted a strict and definitive layout for rules. | |
| # TODO: Could "any" (between ${subnet} and ${ports}) be a catch-all for another subnet? Should we change it? | |
| rule() { | |
| local flow="" # Define the traffic flow | |
| local port="" # Set the port to use, or range of ports separated by a colon. | |
| local proto="" # Set which protocol to use, either tcp or udp | |
| local comment="" # Describe what each rule does. | |
| local suffix=false # Should the protocol be part of comment in the rule? | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| # Flow (Defines traffic permission) | |
| -a | --allow | --allow-in) flow="allow in" ;; # Allow incoming traffic | |
| -A | --allow-out) flow="allow out" ;; # Allow outgoing traffic | |
| -l | --limit | --limit-in) flow="limit" ;; # Like "allow in" but rate-limits repeated attempt (e.g. brute-force SSH) | |
| -d | --deny | --deny-in) flow="deny in" ;; # Denies incoming traffic | |
| -D | --deny-out) flow="deny out" ;; # Denies outgoing traffic | |
| -r | --reject | --reject-in) flow="reject in" ;; # Like "deny in", but sends back an ICMP "connection refused" response. | |
| -R | --reject-out) flow="reject out" ;; # Like "deny out", but sends back an ICMP "connection refused" respose. | |
| # Port and Protocol | |
| -t | --tcp) | |
| shift | |
| port="$1" | |
| proto="tcp" | |
| ;; | |
| -T) | |
| shift | |
| port="$1" | |
| proto="tcp" | |
| suffix=true | |
| ;; | |
| -u | --udp) | |
| shift | |
| port="$1" | |
| proto="udp" | |
| ;; | |
| -U) | |
| shift | |
| port="$1" | |
| proto="udp" | |
| suffix=true | |
| ;; | |
| # Comment | |
| -C | --comment) | |
| shift | |
| comment="$1" | |
| ;; | |
| # Other | |
| *) | |
| echo "${RED}ERROR:${NC} Unknown option: ${YELLOW}$1${NC}" >&2 | |
| return 1 | |
| ;; | |
| esac | |
| shift | |
| done | |
| if [[ -z ${flow} || -z ${port} || -z ${proto} || -z ${comment} ]]; then | |
| echo "${RED}ERROR:${NC} Missing required argument. Flow, port, protocol, and comment are manditory." >&2 | |
| return 1 | |
| fi | |
| [[ ${suffix} == true ]] && comment="${comment} ${proto^^}" | |
| ufw ${flow} from ${LAN_SUBNET_v4} to any port ${port} proto ${proto} comment "${comment} (IPv4)" | |
| ufw ${flow} from ${LAN_SUBNET_v6} to any port ${port} proto ${proto} comment "${comment} (IPv6)" | |
| } | |
| echo -e "${YELLOW}Network Printing${NC}" | |
| echo -e "${GREEN}I want to ask about Network Printing.${NC}" | |
| ALLOW_NETWORK_PRINTING=$(prompt_yn "Do you plan on using network printing?" && echo true || echo false) | |
| ALLOW_BROTHER=false | |
| if [[ ${ALLOW_NETWORK_PRINTING} == true ]]; then | |
| ALLOW_BROTHER=$(prompt_yn "Do you want to add rules for Brother Scanner ports (8611/tcp & 8612/tcp)?" && echo true || echo false) | |
| else | |
| ALLOW_BROTHER=false | |
| fi | |
| echo -e "${YELLOW}Multicast DNS (mDNS)${NC}" | |
| echo -e "${GREEN}Multicast DNS can allow you to access this device via the hostname.${NC} (e.g. ${YELLOW}$(uname -n).local${NC} instead of ${YELLOW}$(get_all_ips)${NC}.)" | |
| ALLOW_MDNS=$(prompt_yn "Do you want to use Multicast DNS for local hostname discovery (also used by CUPS, Avahi, Bonjour)?" && echo true || echo false) | |
| ALLOW_WSD=false | |
| if [[ ${ALLOW_MDNS} == true ]]; then | |
| ALLOW_WSD=$(prompt_yn "Do you want to use Web Services Dynamic Discovery (WS-Discovery)?" "N" && echo true || echo false) | |
| else | |
| ALLOW_WSD=false | |
| fi | |
| echo -e "${YELLOW}E-mail Services${NC}" | |
| ALLOW_MAIL_CLIENT=$(prompt_yn "Do you plan on using an email client on your computer to send and retrieve mail?" && echo true || echo false) | |
| ALLOW_MAIL_SERVER=$(prompt_yn "Do you plan on using your computer as an email server?" "N" && echo true || echo false) | |
| echo -e "${YELLOW}File Sharing${NC}" | |
| ALLOW_SAMBA=$(prompt_yn "Do you plan on using Samba for sharing files between devices?" && echo true || echo false) | |
| ALLOW_NFS=$(prompt_yn "Do you want to allow NFS access (portmapper and daemon)?" && echo true || echo false) | |
| ALLOW_BITTORRENT=$(prompt_yn "Do you plan on using a BitTorrent client for file sharing?" && echo true || echo false) | |
| ALLOW_MEGA=$(prompt_yn "Do you plan on using MEGA file transfer service?" && echo true || echo false) | |
| echo -e "${YELLOW}Remote Desktop Services${NC}" | |
| ALLOW_REMOTE=$(prompt_yn "Do you plan on using any remote desktop services?" && echo true || echo false) | |
| ALLOW_VNC=false | |
| ALLOW_TEAMVIEWER=false | |
| ALLOW_RUSTDESK=false | |
| ALLOW_RUSTDESK_OUTSIDE=false | |
| if [[ ${ALLOW_REMOTE} == true ]]; then | |
| echo -e "${GREEN}There are a few softwares that do remote computing, so I want to ask about them.${NC}" | |
| ALLOW_VNC=$(prompt_yn "Do you plan on using VNC viewer?" && echo true || echo false) | |
| ALLOW_TEAMVIEWER=$(prompt_yn "Do you plan on using Team Viewer?" "N" && echo true || echo false) | |
| ALLOW_RUSTDESK=$(prompt_yn "Do you plan on using RustDesk?" && echo true || echo false) | |
| if [[ ${ALLOW_RUSTDESK} == true ]]; then | |
| ALLOW_RUSTDESK_OUTSIDE=$(prompt_yn "Do you plan on using RustDesk outside your local network?" "N" && echo true || echo false) | |
| else | |
| ALLOW_RUSTDESK_OUTSIDE=false | |
| fi | |
| else | |
| ALLOW_VNC=false | |
| ALLOW_TEAMVIEWER=false | |
| ALLOW_RUSTDESK=false | |
| fi | |
| echo -e "${YELLOW}Other services${NC}" | |
| echo -e "${GREEN}Finally, other services.${NC}" | |
| ALLOW_SDR=$(prompt_yn "Do you plan on using Software Defined Radio (SDR) with rtl_tcp?" && echo true || echo false) | |
| # Flight confirmation checklist | |
| echo "Just to confirm..." | |
| echo | |
| echo "== Device IP Addresses ==" | |
| echo "IPv4: ${ipv4}" | |
| echo "IPv6: ${ipv6}" | |
| echo "== Subnets ==" | |
| echo "LAN Subnet (IPv4): ${LAN_SUBNET_v4}" | |
| echo "LAN Subnet (IPv6): ${LAN_SUBNET_v6}" | |
| echo "== Network services == " | |
| echo "Allow Network Printing: ${ALLOW_NETWORK_PRINTING}" | |
| echo "Allow Brother Scanning: ${ALLOW_BROTHER}" | |
| echo "Allow mDNS for local host name discovery: ${ALLOW_MDNS}" | |
| echo "Allow WS-Discovery: ${ALLOW_WSD}" | |
| echo "== Email Services ==" | |
| echo "Allow Mail Client ${ALLOW_MAIL_CLIENT}" | |
| echo "Allow Mail Server ${ALLOW_MAIL_SERVER}" | |
| echo "== File Sharing ==" | |
| echo "Allow Samba: ${ALLOW_SAMBA}" | |
| echo "Allow NFS: ${ALLOW_NFS}" | |
| echo "Allow BitTorrent: ${ALLOW_BITTORRENT}" | |
| echo "Allow MEGA: ${ALLOW_MEGA}" | |
| echo "== Remote Desktop Services ==" | |
| echo "Allow Remote Services: ${ALLOW_REMOTE}" | |
| echo "Allow VNC: ${ALLOW_VNC}" | |
| echo "Allow TeamViewer: ${ALLOW_TEAMVIEWER}" | |
| echo "Allow RustDesk: ${ALLOW_RUSTDESK}" | |
| echo "Allow RustDesk outside local network: ${ALLOW_RUSTDESK_OUTSIDE}" | |
| echo "== Other Services ==" | |
| echo "Allow rtl_tcp for Software Defined Radio: ${ALLOW_SDR}" | |
| echo | |
| if ! prompt_yn "Is this correct?" "Y"; then | |
| echo "Aborted. No changes made." | |
| exit 0 | |
| fi | |
| echo -e "${GREEN}Awesome. Let's get down to business.${NC}" | |
| # Service sanity check | |
| echo -e "${GREEN}Checking for services...${NC}" | |
| service_sanity_check | |
| echo -e "${GREEN}All checks are passed. Proceding with UFW setup...${NC}" | |
| # Disable UFW before resetting the rules. | |
| echo -e "${GREEN}Disabling UFW.${NC}" | |
| ufw --force disable | |
| # Force reset of UFW configuration. (This will likely blank out all your rules.) | |
| # NOTE: Apparently, when you run this command, ufw will backup all the rules into some '.rules' files. | |
| # TODO: Needs refinement. Makes sure we aren't making a lot of old rules files if we run this more than once. | |
| echo -e "${GREEN}Clearing out the old rules.${NC}" | |
| ufw --force reset | |
| # Disable UFW logging (quiet operation; avoids jamming up journalctl with pings and handshake messages) | |
| # NOTE: This can be changed to "low" for diagnostics | |
| echo -e "${GREEN}Disabling logging so it doesn't flood journalctl with pings and handshakes${NC}" | |
| ufw logging off | |
| # Set the default policies | |
| echo -e "${GREEN}Setting the default policies.${NC}" | |
| ufw default deny incoming | |
| ufw default allow outgoing | |
| # Allow all LAN devices from local network only. | |
| echo -e "${GREEN}Setting up rules to allow all LAN devices from the local network.${NC}" | |
| comment="Allow form local LAN" | |
| ufw allow from "${LAN_SUBNET_v4}" comment "${comment} (IPv4)" | |
| ufw allow from "${LAN_SUBNET_v6}" comment "${comment} (IPv6)" | |
| # Allow SSH with limit from local network only. | |
| echo -e "${GREEN}Setting up rules for SSH${NC}" | |
| rule -l -t 22 -C "SSH from LAN" | |
| # Web Traffic (HTTP/HTTPS) (if local services or future self-hosting is needed) | |
| echo -e "${GREEN}Setting up rules for Web Traffic (http/https)${NC}" | |
| # ufw allow 80/tcp comment "HTTP (IPv4+IPv6)" | |
| # ufw allow 443/tcp comment "HTTPS (IPv4+IPv6)" | |
| rule -a -t 80 -C "HTTP" | |
| rule -a -t 443 -C "HTTPS" | |
| # Printer access on LAN | |
| # if prompt_yn "Do you plan on using network printing?"; then ... fi | |
| if [[ ${ALLOW_NETWORK_PRINTING} == true ]]; then | |
| # Most network printers use IPP (Internet Printing Protocol), JetDirect, or SNMP | |
| echo -e "${GREEN}Setting up rules for network printer and scanner access on LAN${NC}" | |
| rule -a -t 631 -C "IPP Printer" | |
| rule -a -t 9100 -C "JetDirect RAW" | |
| rule -a -t 161 -C "SNMP Discovery" | |
| # I wanted at least one nested question | |
| # if prompt_yn "Do you want to add rules for Brother Scanner ports (8611/tcp & 8612/tcp)?"; then .., fi | |
| if [[ ${ALLOW_BROTHER} == true ]]; then | |
| echo -e "${GREEN}Setting up rules for Brother Scanners${NC}" | |
| # Uncomment if your printer/scanner uses port 8611 or 8612 for scanning. | |
| # If you have a Brother scanner or All-in-one, you will definitely want this. | |
| # 8611/tcp = Brother network scanning (BRScan) - Only for Brother network scanners | |
| # 8612/tcp = Brother encrypted scanning (BRScanSecure) - Only if using secure scanning | |
| rule -a -t 8611 -C "Brother Scanner (BRScan)" | |
| rule -a -t 8612 -C "Brother Scanner (BRSecureScan)" | |
| fi | |
| fi | |
| # Multicast DNS | |
| # if prompt_yn "Do you want to use Multicast DNS for local hostname discovery (also used by CUPS, Avahi, Bonjour)?"; then ... fi | |
| if [[ ${ALLOW_MDNS} == true ]]; then | |
| echo -e "${GREEN}Setting up rules for mDNS local hostname discovery${NC}" | |
| # mDNS Avahi | |
| rule -a -u 5353 -C "Multicast DNS (mDNS)" | |
| # WS-Discovery (Web Services Dynamic Discovery) uses IP multicast address 239.255.255.250 or ff02::c. | |
| # WS-Discovery is enabled by default on networked HP printers. | |
| if [[ ${ALLOW_WSD} == true ]]; then | |
| echo -e "${GREEN}Setting up rules for WS-Discovery${NC}" | |
| rule -a -u 3702 -C "WS-Discovery" | |
| fi | |
| fi | |
| # Email! | |
| if [[ ${ALLOW_MAIL_CLIENT} == true ]]; then | |
| echo -e "${GREEN}Setting up rules for e-mail client${NC}" | |
| rule -a -t 587 -C "SMTP Submission (to send mail)" | |
| rule -a -t 993 -C "IMAPS Server (to receive mail)" | |
| fi | |
| if [[ ${ALLOW_MAIL_SERVER} == true ]]; then | |
| echo -e "${GREEN}Setting up rules for e-mail server${NC}" | |
| rule -a -t 25 -C "SMTP to receive mail from other servers" # Most of you won't need this. | |
| fi | |
| # Samba support with NetBios ports | |
| # if prompt_yn "Do you plan on using Samba for sharing files between devices?"; then ... fi | |
| if [[ ${ALLOW_SAMBA} == true ]]; then | |
| echo -e "${GREEN}Setting up rules for Samba and NetBIOS${NC}" | |
| rule -a -u 137 -C "NetBIOS name service" | |
| rule -a -u 138 -C "NetBIOS datagram service" | |
| rule -a -t 139 -C "SMB over NetBIOS session service" | |
| rule -a -t 445 -C "Samba SMBv2/v3 Direct over TCP" | |
| fi | |
| # NFS Access | |
| # if prompt_yn "Do you want to allow NFS access (portmapper and daemon)?"; then ... fi | |
| if [[ ${ALLOW_NFS} == true ]]; then | |
| echo -e "${GREEN}Setting up rules for NFS${NC}" | |
| rule -a -t 111 -C "NFS Portmapper" | |
| rule -a -t 2049 -C "NFS daemon" | |
| fi | |
| # BitTorrent (qBittorrent-style: default TCP 6881 + optional UDP) | |
| # if prompt_yn "Do you plan on using a BitTorrent client for file sharing?"; then ... fi | |
| if [[ ${ALLOW_BITTORRENT} == true ]]; then | |
| echo -e "${GREEN}Setting up rules for BitTorrent${NC}" | |
| # ufw allow 6881/tcp comment "BitTorrent TCP (IPv4+IPv6)" | |
| # ufw allow 6881/udp comment "BitTorrent UCP (IPv4+IPv6)" | |
| rule -a -T 6881:6889 -C "BitTorrent" | |
| rule -a -U 6881:6889 -C "BitTorrent" | |
| fi | |
| # MEGA File Transfer | |
| # if prompt_yn "Do you plan on using MEGA file transfer service?"; then ... fi | |
| if [[ ${ALLOW_NFS} == true ]]; then | |
| echo -e "${GREEN}Setting up rules for MEGA file${NC}" | |
| rule -a -t 63440:63450 -C "MEGA file transfer" | |
| fi | |
| # Remote Desktop Services | |
| if [[ ${ALLOW_REMOTE} == true ]]; then | |
| echo -e "${GREEN}Setting up rules for remote desktop services${NC}" | |
| # VNC (Display ports 5900-5910, TCP) | |
| # TODO: Does this include tightVNC and other VNC services? | |
| if [[ ${ALLOW_VNC} == true ]]; then | |
| echo -e "${GREEN}Setting up VNC rules${NC}" | |
| rule -a -t 5900:5910 -C "VNC Display" | |
| fi | |
| # TeamViewer (TCP only) | |
| if [[ ${ALLOW_TEAMVIEWER} == true ]]; then | |
| echo -e "${GREEN}Setting up RustDesk rules for local network${NC}" | |
| rule -a -t 5938 -C "TeamViewer" | |
| fi | |
| # RustDesk | |
| if [[ ${ALLOW_RUSTDESK} == true ]]; then | |
| if [[ ${ALLOW_RUSTDESK_OUTSIDE} == true ]]; then | |
| # Rust Desk rules for outside external access (WAN) (Required if acting as a rely or rendezvous) | |
| echo -e "${GREEN}Setting up RustDesk rules for outside network${NC}" | |
| # RustDesk External Access (WAN) - Required if acting as relay/rendezvous | |
| rule -a -t 21112 -C "RustDesk Relay Server" # (hbbs) | |
| rule -a -t 21113 -C "RustDesk Rendezvous Server" # (hbbs) | |
| rule -a -t 21114 -C "RustDesk WebSocket Server" # (Optional) | |
| fi | |
| # RustDesk (local network, TCP & UDP: 21115-21119) | |
| echo -e "${GREEN}Setting up RustDesk rules for local network${NC}" | |
| rule -a -T 21115:21119 -C "RustDesk LAN Access" | |
| rule -a -U 21115:21119 -C "RustDesk LAN Access" | |
| fi | |
| fi | |
| # Software Defined Radio (SDR) | |
| # SDR apps might expose local TCP servers (e.g. rtl_tcp uses port 1234) | |
| # if prompt_yn "Do you plan on using Software Defined Radio (SDR) with rtl_tcp?"; then ... fi | |
| if [[ ${ALLOW_SDR} == true ]]; then | |
| echo -e "${GREEN}Setting up rules for rtl_tcp for Software Defined Radio (SDR)${NC}" | |
| rule -a -t 1234 -C "SDR rtl_tcp stream" | |
| fi | |
| # Enable UFW | |
| echo -e "${GREEN}Enabling UFW.${NC}" | |
| ufw --force enable | |
| # Show the results of our rule set. | |
| echo -e "${GREEN}OK, Let's see what we got.${NC}" | |
| echo | |
| ufw status verbose |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment