1
+ #! /bin/sh
2
+
3
+ # # Declaring an array with URI's of dynamic IP services
4
+ # # New line each in double quotes
5
+ service=(
6
+ " example.dynamic.dns.domain.tld"
7
+ )
8
+
9
+ # # The port to be made available
10
+ port=22
11
+
12
+ # # The service name which is used in the comments and helps with filtering the rules
13
+ # # Example: SSH from Dynamic IP
14
+ name=" SSH"
15
+
16
+ # # If `true` AAAA records will also be fetched from the DNS
17
+ # # Enabled on by default, if you do not want to check for IPv6 simply set to `false`
18
+ ipv6=true
19
+
20
+ # # Declaring an array that will store logs messages
21
+ log=()
22
+
23
+ # # When true an error was raised that needs to be reported
24
+ error=false
25
+
26
+ # # Gets all the DNS records A and AAAA, then returns them as an array
27
+ function get_dns {
28
+ log+=(" - Fetching DNS..." )
29
+
30
+ # # Fetches the A records
31
+ a4=($( dig +short +noall +answer +multiline $1 A) )
32
+
33
+ # # Will also fetch the AAAA record when IPv6 is enabled
34
+ a6=()
35
+ if [ " $ipv6 " = true ]; then
36
+ a6=($( dig +short +noall +answer +multiline $1 AAAA) )
37
+ fi
38
+
39
+ dns=(" ${a4[@]} " " ${a6[@]} " )
40
+
41
+ if [ ! ${# dns[@]} -eq 0 ]; then
42
+ log+=(" -- Successfully fetched DNS records!" )
43
+ else
44
+ log+=(" -- No DNS records fetched!" )
45
+ error=true
46
+ fi
47
+ }
48
+
49
+ # # Filters the firewall rules and extracts the index and address
50
+ function get_existing {
51
+ log+=(" - Fetching Firewall rules..." )
52
+ existing=()
53
+
54
+ while read index ip; do
55
+ existing[index]=$ip ;
56
+ done < <(
57
+ ufw status numbered |
58
+ grep -e ' ' " $port " ' ' |
59
+ grep -i ' ' " $name " ' from Dynamic IP (' " $1 " ' )' |
60
+ awk ' {gsub(/[][]/,""); print $1, $5}'
61
+ )
62
+
63
+ if [ ! ${# existing[@]} -eq 0 ]; then
64
+ log+=(" -- Successfully fetched existing rules!" )
65
+ else
66
+ log+=(" -- No rules fetched!" )
67
+ fi
68
+ }
69
+
70
+ # # Check each service individually
71
+ for s in " ${service[@]} "
72
+ do
73
+ log+=(" Processing $s ..." )
74
+
75
+ get_dns $s
76
+ get_existing $s
77
+
78
+ # # Checking if any records exists for addresses in DNS record
79
+ for a in " ${dns[@]} " ; do
80
+
81
+ log+=(" > Checking $a ..." )
82
+
83
+ # # Create a new rule if nothing was found for the address
84
+ if [[ ! " ${existing[*]} " =~ " $a " ]]; then
85
+
86
+ log+=(" -> No rules found! Adding..." )
87
+ create=$( ufw allow from $a to any port $port comment ' ' " $name " ' from Dynamic IP (' " $s " ' )' )
88
+
89
+ # # Make sure it was successfully created, if not log any errors
90
+ if [[ $create == * " Rule added" * || $c == * " Skipping adding existing rule" * ]]; then
91
+ log+=(" --> Successfully added!" )
92
+ else
93
+ log+=(" --> Failed! Error: $create " )
94
+ error=true
95
+ fi
96
+ else
97
+ log+=(" OK" )
98
+ fi
99
+ done
100
+
101
+ # # Checking if addresses of any existing rules are in the DNS record
102
+ for i in " ${! existing[@]} " ; do
103
+
104
+ log+=(" > Checking record [$i ] -> ${existing[i]} ..." )
105
+
106
+ # # Delete the record if it's address is no longer in the DNS record
107
+ if [[ ! " ${dns[*]} " =~ " ${existing[i]} " ]]; then
108
+
109
+ log+=(" -> Not found in DNS record! Deleting..." )
110
+ delete=$( ufw --force delete $i )
111
+
112
+ # # Make sure it was successfully deleted, if not log any errors
113
+ if [[ $delete == * " Rule deleted" * ]]; then
114
+ log+=(" --> Successfully deleted!" )
115
+ else
116
+ log+=(" --> Failed! Error: $delete " )
117
+ error=true
118
+ fi
119
+ else
120
+ log+=(" OK" )
121
+ fi
122
+ done
123
+ done
124
+
125
+ # # Check if any error have occurred
126
+ # # Prints the log if there is an error and exits with an error coded
127
+ if [ " $error " = true ]; then
128
+ for l in " ${log[@]} " ; do
129
+ echo $l
130
+ done
131
+ exit 1
132
+ else
133
+ exit 0
134
+ fi
0 commit comments