As most people know you have to open port 8089 to the world for remote viewing. Per some topics some people (along with myself) are concerned about having that port open to the world and all the scanning that happens to that port when it's open to the world. You can run a VPN to help resolve/mitigate this issue (I run OpenVPN instead of Tailscale) but when you're using a stick like Chromecast or Firestick you have issues running a VPN on them. I know there are some backdoors to trying to run a VPN on sticks and unless things have changed the vendors are constantly messing with things that make it difficult. So to limit my exposure I looked into the IP addresses that were being used to deliver the remote content. It seems all the addresses that remote viewing was using were AWS EC2 addresses. So after testing this for multiple days it seems remote viewing is working fine when I enable it and allow all AWS EC2 subnets into my server.
So for anyone that is interested here is the script I use to gather the AWS EC2 subnets and create an nftables "set" file that I can load into nftables when I want to remotely stream when a VPN isn't an option. If you're using an older version of linux that uses iptables then you can easily modify the script to create an ipset.
To use that "set" you need the following 2 rules in your main nftables file. First you need to import that "set" file after you define your filter table in your main nftables file using the following line: NOTE: my file is called channels_dvr.set but you can call it whatever you want.
include "/etc/nftables/channels_dvr.set"
Now that the "set" is imported you can now enable the following filter rule whenever you want to turn on remote viewing: NOTE: Change "inet filter NFT-INPUT" to whatever your filter type/chain name you use.
# Allow remote access to Channels DVR
add rule inet filter NFT-INPUT ip saddr @CHANNELS_DVRv4 tcp dport 8089 counter accept
Here is the perl script I use to create the set file that you copy to the /etc/nftables directory. I usually place the file in my home directory but the script below places it in /tmp. Also, in the "Write last lines" section change the IP address to the private local address of your internet router since some traffic will come from that. To make things easier per the way amazon presents the file I use curl instead of per modules for the download. Also, yes I can check the download status and add more logic but I look at the file that gets created and know whether there was an issue or not.
> cat get_amazon_ec2_addresses
#!/usr/bin/perl
#
# This script downloads the Amazon AWS ip-ranges.json file which contains
# all its IP address ranges. It then extracts all the EC2 addresses from
# the file and places them in the firewall to allow port 8089 for
# Channel DVR's remote DVR service.
# Include any necessary modules
use lib qw(..);
use JSON qw( );
# Initialize misc variables
$channels_dvr_set_file = "/tmp/channels_dvr.set";
$ip_ranges_file_url = "https://ip-ranges.amazonaws.com/ip-ranges.json";
$ip_ranges_file = "/tmp/channels_dvr.set";
$temp_file = "/tmp/ip-ranges.json.tmp";
# Make sure the channels dvr nftables set file exists and has the
# correct permissions.
open (CDVR, ">>$channels_dvr_set_file") || die "Can NOT open for write the channels dvr nftables set file $channels_dvr_set_file $! : ABORTING...";
close (CDVR);
chmod 0755, $channels_dvr_set_file;
# Download the Amazon AWS ip-ranges.json file
$download_status = `/usr/bin/curl -o $temp_file $ip_ranges_file_url > /dev/null 2>&1`;
open (AWSIPS, ">$ip_ranges_file") || die "Can NOT open for write the new IP Ranges file $ip_ranges_file $! : ABORTING...";
# Write first lines of new Amazon AWS IP ranges set file
print AWSIPS "#!/usr/sbin/nft -f\n";
print AWSIPS "\n";
print AWSIPS "add set inet filter CHANNELS_DVRv4 { type ipv4_addr; flags interval; }\n";
print AWSIPS "\n";
print AWSIPS "add element inet filter CHANNELS_DVRv4 {\n";
$json_text = do {
open ($json_fh, "<:encoding(UTF-8)", $temp_file) || die "Can NOT open for read the temporary Amazon AWS IP ranges file $temp_file: $!\n";
local $/;
<$json_fh>
};
$json = JSON->new;
$data = $json->decode($json_text);
for (@{$data->{prefixes}}) {
if ($_->{service} eq "EC2") {
print AWSIPS $_->{ip_prefix}.",\n";
}
}
# Write last lines of new Amazon AWS IP ranges set file
print AWSIPS "192.168.x.x/32\n";
print AWSIPS "}\n";
close (AWSIPS);
exit (0);
Hopefully the above script will help others using linux and want to limit their exposure when wanting to enable remote viewing.