Skip to content

Instantly share code, notes, and snippets.

@jrcharney
Last active April 24, 2025 00:30
Show Gist options
  • Select an option

  • Save jrcharney/d70f02d11f5e5fb0c10093fdd07a268d to your computer and use it in GitHub Desktop.

Select an option

Save jrcharney/d70f02d11f5e5fb0c10093fdd07a268d to your computer and use it in GitHub Desktop.
Interactive UFW setup script
#!/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