forked from gitbls/sdm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sdm-hotspot
executable file
·323 lines (305 loc) · 8.76 KB
/
sdm-hotspot
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
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
#!/bin/bash
#
# See (Routed/Local): https://www.raspberrypi.org/documentation/configuration/wireless/access-point-routed.md
# AND (Bridged): https://www.raspberrypi.org/documentation/configuration/wireless/access-point-bridged.md
#
# NOTES
# Use sudo systemctl disable sdm-hostapd-iptables to disable routing if desired
# hwmode G doesn't work well (at least with channel 7. Test more)
#
# Hotspot type:
# local: Clients can only access the IP of the hotspot (web pages, etc)
# routed: Clients can access the IP of the hotspot AND the network to which hotspot is connected
# bridged: Clients appear to become part of the network to which the hotspot is connected
#
# To use without sdm:
# * Invoke with 'sudo sdm-hotspot config-file`
# * See https://github.com/gitbls/sdm/README.md for details on the --hotspot config-file
#
function saveorig() {
#
# $1 = filename to save
# $2 = "" (move file to .orig) or 1 (keep original and copy to .orig)
# Only renames it to $1.orig if $1.orig doesn't already exist
# If $1.orig already exists, the file $1 is simply deleted
#
[ ! -f $1 ] && return
[ -f $1.orig ] && ( [ "$2" != "1" ] && rm -f $1 ; return )
[ "$2" == "1" ] && cp $1 $1.orig || mv $1 $1.orig
return
}
function logtoboth() {
#
# Overridden if used in sdm
#
echo "$1"
return
}
function doapt() {
#
# Overridden if used in sdm
#
apt $1
return
}
# $SDMNSPAWN != "" if called from within sdm
if [ "$SDMNSPAWN" != "" ]
then
source /etc/sdm/sdm-readparams
# sdm copies the hotspot config file into the image in sdm-phase0
fhotspot="/etc/sdm/assets/$(basename $hotspot)"
else
fhotspot="$1"
fi
logtoboth "* Start Access Point (hotspot) installation and configuration"
#
# set defaults
#
hotconfig="local" #local|routed|bridged
hotchannel="36"
hothwmode="a"
hotcountry=$wificountry
hotdev="wlan0"
hotwlanip="192.168.4.1"
hotdhcprange="192.168.4.2,192.168.4.32,255.255.255.0" #? Is netmask needed?
hotleasetime="24h"
hotssid="MyPiNet"
hotpassphrase="password"
hotdomain="wlan.net"
hotenable="true"
hotinclude=""
while IFS=":=" read rpifun value
do
if [[ ! $rpifun =~ ^\ *# && -n $rpifun ]] # skip comment and malformed lines
then
value="${value%%\#*}" # Del EOL comments
value="${value%"${value##*[^[:blank:]]}"}" # Del trailing spaces/tabs
value="${value#\"}" # Del opening double-quotes
value="${value%\"}" # Del closing double-quotes
value="${value#\'}" # Del opening single-quotes
value="${value%\'}" # Del closing single-quotes
case "${rpifun,,}" in
# * do_resolution still needs to be sorted out
channel)
hotchannel=$value
;;
config)
hotconfig=${value,,}
;;
country)
hotcountry=${value,,}
;;
dev|device)
hotdev=${value,,}
;;
dhcprange|dhcp-range)
hotdhcprange=$value
;;
domain)
hotdomain=${value,,}
;;
enable)
hotenable=${value,,}
;;
hwmode|hw-mode)
hothwmode=${value,,}
;;
leasetime|lease-time)
hotleasetime=$value
;;
passphrase|password)
hotpassphrase=$value
;;
ssid)
hotssid=$value
;;
wlanip|wlan-ip)
hotwlanip=$value
;;
include)
hotinclude=$value
;;
*)
logtoboth "% Unrecognized hotspot option '$rpifun' in '$fhotspot'"
;;
esac
fi
done < $fhotspot
#
# Validity checks
#
if [[ ! "local|routed|bridged" =~ "$hotconfig" ]] || [ "$hotconfig" == "" ]
then
logtoboth "? Unrecognized Access Point configuration type '$hotconfig'"
exit
fi
if [ "$hotinclude" != "" ]
then
[ ! -f $hotinclude ] && logtoboth "% hostapd.conf include file '$hotinclude' not found; ignoring"
fi
# install hostapd and dnsmasq
svcs="hostapd"
logtoboth "> Install and disable hostapd"
[ "$SDMNSPAWN" == "" ] && logtoboth "% Ignore any service start errors"
doapt "install --no-install-recommends --yes hostapd" "$showapt"
systemctl unmask hostapd
systemctl disable hostapd
if [ "$hotconfig" != "bridged" ]
then
logtoboth "> Install and disable dnsmasq"
svcs="hostapd and dnsmasq"
doapt "install --no-install-recommends --yes dnsmasq" "$showapt"
systemctl disable dnsmasq
fi
[ "$SDMNSPAWN" != "" ] && logtoboth "% $svcs will be re-enabled during FirstBoot"
# Create hostapd and dnsmasq config files
logtoboth "> hostapd will be configured for mode '$hotconfig'"
logtoboth "> Create hostapd configuration"
saveorig /etc/hostapd/hostapd.conf
echo "# sdm hostapd configuration $(date)" > /etc/hostapd/hostapd.conf
echo "interface=$hotdev" >> /etc/hostapd/hostapd.conf
[ "$hotconfig" == "bridged" ] && echo "bridge=br0" >> /etc/hostapd/hostapd.conf
cat >> /etc/hostapd/hostapd.conf <<EOF
country_code=${hotcountry^^}
# use ssid2 for double-quoted string, hexdump, or printf-escaped string
ssid=$hotssid
hw_mode=$hothwmode
# See https://en.wikipedia.org/wiki/List_of_WLAN_channels for list of WLAN channels
channel=$hotchannel
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=$hotpassphrase
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
#
# hostapd event logger configuration (from /usr/share/doc/hostapd/examples/hostapd.conf)z
#
# Two output method: syslog and stdout (only usable if not forking to
# background).
#
# Module bitfield (ORed bitfield of modules that will be logged; -1 = all
# modules):
# bit 0 (1) = IEEE 802.11
# bit 1 (2) = IEEE 802.1X
# bit 2 (4) = RADIUS
# bit 3 (8) = WPA
# bit 4 (16) = driver interface
# bit 5 (32) = IAPP
# bit 6 (64) = MLME
#
# Levels (minimum value for logged events):
# 0 = verbose debugging
# 1 = debugging
# 2 = informational messages
# 3 = notification
# 4 = warning
#
logger_syslog=-1
logger_syslog_level=1
logger_stdout=-1
logger_stdout_level=1
EOF
# Cat the include file to the end of hostpad.conf if specified
[ "$hotinclude" != "" ] && cat $hotinclude >> /etc/hostapd/hostapd.conf
if [ "$hotconfig" != "bridged" ]
then
logtoboth "> Create dnsmasq configuration"
saveorig /etc/dnsmasq.conf 1
cat >> /etc/dnsmasq.conf <<EOF
# sdm hotspot dnsmasq configuration $(date)
interface=$hotdev
dhcp-range=$hotdhcprange,$hotleasetime
domain=$hotdomain
address=/gw.$hotdomain/$hotwlanip
EOF
fi
# if routed enable sysctl routing
if [ "$hotconfig" == "routed" ]
then
logtoboth "> Enable routing and masquerading for WiFi clients onto LAN"
cat > /etc/sysctl.d/040-sdm-aprouted.conf <<EOF
# sdm hotspot routing configured on $(date)
# https://www.raspberrypi.org/documentation/configuration/wireless/access-point-routed.md"
# Enable IPv4 routing
net.ipv4.ip_forward=1
EOF
logtoboth "> Configure service sdm-hostapd-iptables to enable iptables routing"
cat > /etc/systemd/system/sdm-hostapd-iptables.service <<EOF
[Unit]
Description=sdm-hostapd-iptables
After=network.target
[Service]
#
# This service should be:
# Enabled for a routed access point
# Disabled for a local or bridged access point
#
ExecStart=/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
RemainAfterExit=true
Type=oneshot
[Install]
WantedBy=multi-user.target
EOF
systemctl enable sdm-hostapd-iptables
fi
if [ "$hotconfig" == "bridged" ]
then
logtoboth "> Configure network bridge br0 and enable systemd-networkd"
cat > /etc/systemd/network/bridge-br0.netdev <<EOF
[NetDev]
Name=br0
Kind=bridge
EOF
cat > /etc/systemd/network/br0-member-eth0.network <<EOF
[Match]
Name=eth0
[Network]
Bridge=br0
EOF
systemctl enable systemd-networkd
saveorig /etc/dhcpcd.conf 1
sed -i '1 i\denyinterfaces wlan0 eth0' /etc/dhcpcd.conf
echo -e "\n# sdm bridged network configuration $(date)" >> /etc/dhcpcd.conf
echo 'interface br0' >> /etc/dhcpcd.conf
else
# update dhcpcd config for local or routed hotspot
logtoboth "> Disable wpa_supplicant configuration for $hotdev in dhcpcd"
cat >> /etc/dhcpcd.conf <<EOF
# sdm $hotconfig network configuration $(date)"
interface $hotdev
static ip_address=$hotwlanip/24
nohook wpa_supplicant
EOF
fi
if [ "$hotenable" == "true" ]
then
if [ "$SDMNSPAWN" != "" ]
then
logtoboth "> Set hostapd and dnsmasq to enable during FirstBoot"
cat > /etc/sdm/0piboot/040-hostapd-enable.sh <<EOF
#!/bin/bash
#source /etc/sdm/sdm-readparams #Not needed at the moment
logger "FirstBoot: Enable hostapd and dnsmasq"
systemctl enable hostapd
rfkill unblock wlan
EOF
[ "$hotconfig" != "bridged" ] && echo "systemctl enable dnsmasq" >> /etc/sdm/0piboot/040-hostapd-enable.sh
chmod 755 /etc/sdm/0piboot/040-hostapd-enable.sh
else # SDMNSPAWN == "" (not in sdm)
systemctl enable hostapd
[ "$hotconfig" != "bridged" ] && systemctl enable dnsmasq
fi
else
if [ "$SDMNSPAWN" == "" ]
then
se="sudo systemctl enable hostapd"
[ "$hotconfig" != "bridged" ] && se="$se ; sudo systemctl enable dnsmasq"
logtoboth "> Use '$se' to enable the hotspot"
fi
fi
logtoboth "* Hotspot Install Completed"
[ "$SDMNSPAWN" == "" ] && logtoboth "" && logtoboth "% Restart your system to ensure configuration is correct"
exit