summaryrefslogtreecommitdiff
path: root/d10-nuc-as-soho-router.sh
blob: 549cab5fc58c6cd411b67fa311aa0a06f65709b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#!/bin/bash 
# Successfully used on Intel NUC 7CJYH and Debian 10 to replace a 
#  Bouygues BBox for French FFTH with external fiber-to-RJ45 module (ONT)

# Edit the following configuration constants to fit your environment
#  If you want eth0, eth1... names, set GRUB_CMDLINE_LINUX="net.ifnames=0"
#   in /etc/default/grub then run update-grub && reboot before running this script.
#
#  For RT_WAN_MAC snif original box mac address by plugging box WAN port
#   to a linux computer and with something like "sudo tcpdump -nei eno1 udp".
#   It happened to work for me with a fake ac:3b:77:01:02:03.

DHCPD_DNSLIST="80.67.169.12,91.224.149.254" # FDN and TTN recursive open-dns
DHCPD_RANGE="192.168.42.10 192.168.42.254"  # Choose min/max IP within RT_LAN_IP/RT_LAN_MASK 
PKGS="isc-dhcp-server ssh vlan"
RT_LAN_IFACE=eth0 # I prefer disabling interface renaming, "stable names" are painful for me
RT_LAN_IP=192.168.42.1
RT_LAN_MASK=255.255.255.0
RT_LAN_NET=192.168.42.0
RT_WAN_IFACE=eth1 # eth1 is my USB network adapter. I don't want Intel NIC on WAN (security).
RT_WAN_MAC=ac:3b:77:01:02:03
RT_WAN_VLAN=100   # Always 100 on Bouygues FTTH network
#SSH_KEY="ssh-rsa AAAA...................ffsU5 lpouzenc@lud-hp1" # no carriage return allowed at all here

ccommand=`tput setaf 3`
ccomment=`tput setaf 6`
crst=`tput sgr0`

overwrite() {
	echo "${ccommand}editor $1${crst}"
	cat > $1
}

trace() {
	echo "${ccommand}$@${crst}"
	"$@"
}

info() {
	echo "${ccomment}# $@${crst}"
}

codename=$(sed -ne 's/^VERSION_CODENAME=//p' /etc/os-release)
if [[ "buster" != "$codename" ]]; then
	read -p "Warning: this script has only be tested on Debian Buster. Enter to continue anyway or Ctrl+C to cancel " unused
fi

set -e

info "apt: install needed packages to have a complete SOHO router"
trace apt update
trace apt install -y $PKGS

info "ssh: will potentially listen on WAN port, disable Password Authentification"
trace sed --in-place \
 -e 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/'\
 /etc/ssh/sshd_config
trace mkdir -p /root/.ssh
[ -n "$SSH_KEY" ] && echo $SSH_KEY | overwrite /root/.ssh/authorized_keys
trace systemctl reload ssh

info "systemd: please don't block for ages, this hardware have normal IO delays"
trace sed --in-place \
 -e 's/^#\?DefaultTimeoutStartSec=.*/DefaultTimeoutStartSec=5s/' \
 -e 's/^#\?DefaultTimeoutStopSec=.*/DefaultTimeoutStopSec=5s/' \
 /etc/systemd/{system,user}.conf
trace mkdir -p /etc/systemd/system/networking.service.d
overwrite /etc/systemd/system/networking.service.d/override.conf <<EOT
[Service]
TimeoutStartSec=20s
EOT

info "ifupdown: start firewall then routing at boot, configure ifaces' IP"
info " Humans should use iptables-apply and ip6tables-apply commands"
overwrite /etc/network/interfaces <<EOT 
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback
	up iptables-restore /etc/network/iptables.up.rules
	up sysctl -w net.ipv4.ip_forward=1
	up sysctl -w net.ipv4.conf.all.accept_redirects=0
	up ip6tables-restore /etc/network/ip6tables.up.rules
	up sysctl -w net.ipv6.conf.all.forwarding=1
	up sysctl -w net.ipv6.conf.all.autoconf=0
	up sysctl -w net.ipv6.conf.all.accept_ra=0
	up sysctl -w net.ipv6.conf.default.autoconf=0
	up sysctl -w net.ipv6.conf.default.accept_ra=0

auto eth0
iface eth0 inet static
	address $RT_LAN_IP
	netmask $RT_LAN_MASK

allow-hotplug $RT_WAN_IFACE
iface $RT_WAN_IFACE inet manual
	pre-up ip link set $RT_WAN_IFACE address $RT_WAN_MAC

allow-hotplug $RT_WAN_IFACE.$RT_WAN_VLAN
iface $RT_WAN_IFACE.$RT_WAN_VLAN inet dhcp
EOT

info "iptables: I left here my rules"
info " drop by default what came from WAN + self-hosting on my NUC + BitTorrent redirect to a host"
info " network doesn't provide IPv6 yet here, ip6tables should be okay but untested"
info " iptables-save and ip6tables-save commands generate this exact file format"
overwrite /etc/network/iptables.up.rules <<EOT 
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:ICMP4 - [0:0]
:LOGDROP - [0:0]
:LOGACCEPT - [0:0]
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -p icmp -j ICMP4
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -m conntrack ! --ctstate NEW -j LOGDROP
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -p tcp -m tcp --dport 25 -j ACCEPT
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -j DROP
-A INPUT -i $RT_WAN_IFACE -j LOGDROP
-A FORWARD -i $RT_WAN_IFACE.$RT_WAN_VLAN -p icmp -j ICMP4
-A FORWARD -i $RT_WAN_IFACE.$RT_WAN_VLAN -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i $RT_WAN_IFACE.$RT_WAN_VLAN -m conntrack --ctstate DNAT -j LOGACCEPT
-A FORWARD -i $RT_WAN_IFACE.$RT_WAN_VLAN -j LOGDROP
-A FORWARD -i $RT_WAN_IFACE -j LOGDROP
-A ICMP4 -p icmp -m limit --limit 10/sec -m icmp --icmp-type 0 -j ACCEPT
-A ICMP4 -p icmp -m limit --limit 10/sec -m icmp --icmp-type 3 -j ACCEPT
-A ICMP4 -p icmp -m limit --limit 10/sec -m icmp --icmp-type 8 -j ACCEPT
-A ICMP4 -p icmp -m limit --limit 10/sec -m icmp --icmp-type 11 -j ACCEPT
-A ICMP4 -m limit --limit 1/sec -j LOG --log-prefix "ICMP4-RATELIMIT "
-A ICMP4 -j DROP
-A LOGDROP -m limit --limit 1/sec -j LOG --log-prefix "LOGDROP "
-A LOGDROP -j DROP
-A LOGACCEPT -m limit --limit 1/sec -j LOG --log-prefix "LOGACCEPT "
-A LOGACCEPT -j ACCEPT
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A PREROUTING -i $RT_WAN_IFACE.$RT_WAN_VLAN -p tcp -m tcp --dport 51413 -j DNAT --to-destination 192.168.42.10:51413
-A PREROUTING -i $RT_WAN_IFACE.$RT_WAN_VLAN -p udp -m udp --dport 51413 -j DNAT --to-destination 192.168.42.10:51413
-A POSTROUTING -o $RT_WAN_IFACE.$RT_WAN_VLAN -j MASQUERADE
COMMIT
EOT

overwrite /etc/network/ip6tables.up.rules <<EOT 
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:ICMP6 - [0:0]
:LOGDROP - [0:0]
:LOGACCEPT - [0:0]
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -p ipv6-icmp -j ICMP6
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -m conntrack ! --ctstate NEW -j LOGDROP
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -p tcp -m tcp --dport 25 -j ACCEPT
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -i $RT_WAN_IFACE.$RT_WAN_VLAN -j DROP
-A INPUT -i $RT_WAN_IFACE -j LOGDROP
-A FORWARD -i $RT_WAN_IFACE.$RT_WAN_VLAN -p ipv6-icmp -j ICMP6
-A FORWARD -i $RT_WAN_IFACE.$RT_WAN_VLAN -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i $RT_WAN_IFACE.$RT_WAN_VLAN -m conntrack ! --ctstate NEW -j LOGDROP
# Put custom IPv6 WAN to LAN forward rules here
-A FORWARD -i $RT_WAN_IFACE.$RT_WAN_VLAN -j LOGDROP
-A FORWARD -i $RT_WAN_IFACE -j LOGDROP
-A ICMP6 -p ipv6-icmp -m limit --limit 10/sec -m ipv6-icmp --icmpv6-type 1 -j ACCEPT
-A ICMP6 -p ipv6-icmp -m limit --limit 10/sec -m ipv6-icmp --icmpv6-type 2 -j ACCEPT
-A ICMP6 -p ipv6-icmp -m limit --limit 10/sec -m ipv6-icmp --icmpv6-type 3 -j ACCEPT
-A ICMP6 -p ipv6-icmp -m limit --limit 10/sec -m ipv6-icmp --icmpv6-type 4 -j ACCEPT
-A ICMP6 -p ipv6-icmp -m limit --limit 10/sec -m ipv6-icmp --icmpv6-type 128 -j ACCEPT
-A ICMP6 -p ipv6-icmp -m limit --limit 10/sec -m ipv6-icmp --icmpv6-type 129 -j ACCEPT
# ICMP rules allowing for NDP or RA from the ISP are probably missing here (untested)
-A ICMP6 -m limit --limit 1/sec -j LOG --log-prefix "ICMP6-RATELIMIT "
-A ICMP6 -j DROP
-A LOGDROP -m limit --limit 1/sec -j LOG --log-prefix "LOGDROP "
-A LOGDROP -j DROP
-A LOGACCEPT -m limit --limit 1/sec -j LOG --log-prefix "LOGACCEPT "
-A LOGACCEPT -j ACCEPT
COMMIT
EOT

info "dhcp: upstream files are full pages of comments, not very usefull in this basic case"
overwrite /etc/dhcp/dhclient.conf <<EOT
send vendor-class-identifier "BYGTELIAD";
request subnet-mask, broadcast-address, routers, domain-name-servers;
EOT

overwrite /etc/dhcp/dhcpd.conf <<EOT
option domain-name-servers $DHCPD_DNSLIST;
default-lease-time 600;
max-lease-time 7200;
ddns-update-style none;
authoritative;
subnet $RT_LAN_NET netmask $RT_LAN_MASK {
  range $DHCPD_RANGE;
  option routers $RT_LAN_IP;
}
EOT

info "Please review modified files and reboot with a screen attached to see if it is going ok"
info "You should tweak BIOS to have no 'Press F1 to continue' on POST errors and Power On when AC come back"
info "Test hard power cutoff and check if everything came back online without interaction after that"