Last active
November 15, 2019 08:35
-
-
Save o0-o/9059e61b02f511d16d1cebf392bfd81d to your computer and use it in GitHub Desktop.
[Onboard a Ubiquiti Edgemax Network] Deploy a baseline Edgemax environment with one router and many switches.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### WORK IN PROGRESS ### | |
#!/usr/bin/env bash | |
set -euo pipefail | |
################################################################################ | |
### DEFINE THE NETWORK ######################################################### | |
################################################################################ | |
## Network | |
################################################################################ | |
# public ip addressing | |
declare -r WAN_IP= #x.x.x.x | |
declare -r WAN_SM= #29 | |
declare -r WAN_GW= #x.x.x.x | |
# site domain | |
declare -r DOM= #dom.tld | |
# site number (0-255) | |
declare -r SITE= #(0-255) | |
# router admin user | |
declare ADMIN_USER= #random_word | |
declare ADMIN_PW= #random_pw | |
## Firmware | |
# should not automatically pull latest update, needs to be updated carefully | |
declare ROUTER_FIRM= #'https://dl.ui.com/firmwares/edgemax/v2.0.x/ER-e300.v2.0.6.5208554.tar' | |
# all edgeswitch firmware in an array. we will correlate firmware based on the | |
# prefix | |
declare -a SWITCH_FIRMS=('https://dl.ui.com/firmwares/edgemax/EdgeSwitch/v1.8.3/ES-eswh.v1.8.3.5233923.stk' 'https://dl.ui.com/firmwares/edgemax/EdgeSwitchXP/v2.0.0/SW.v2.0.0.99.190920.1050.bin' 'https://dl.ui.com/firmwares/edgemax/EdgeSwitch/v1.8.3/ES-esgh.v1.8.3.5233923.stk' 'https://dl.ui.com/firmwares/edgemax/EdgeSwitchX/v1.1.3/ESX.1.1.3.bix') | |
## Command Shortcuts | |
################################################################################ | |
# vyatta configure wrapper | |
CFG=/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper | |
# vyatta operational wrapper | |
OP=/opt/vyatta/bin/vyatta-op-cmd-wrapper | |
################################################################################ | |
### MINIMAL ROUTER CONFIGURATION ############################################### | |
################################################################################ | |
# | |
# 1. Register SSH Key for Default Admin | |
# 2. Create new Admin User | |
# 3. Register an SSH Key for New Admin User | |
# 4. Delete Default User | |
# 5. Clear EULA Prompt | |
# | |
################################################################################# | |
# | |
# if SSH is not enabled by default, log into the web GUI and enable it, or use | |
# this script to enable it with cURL. | |
# | |
# https://gist.github.com/69fa55610d8643a0eeb1d241c3908f47#file-enable_ssh_on_edgeos_via_https-sh | |
# | |
################################################################################ | |
## Register SSH Key for Default Admin | |
################################################################################ | |
# ubiquiti defaults | |
USER=${"ubnt"} | |
PW=${"ubnt"} | |
HOST=${"192.168.1.1"} | |
# set up temporary key | |
sed -i -e "s/${HOST}.*//" \ | |
"${HOME}/.ssh/known_hosts" | |
rm ~/.ssh/${USER}@${HOST} \ | |
~/.ssh/${USER}@${HOST}.pub 2>/dev/null || : | |
ssh-keygen -t rsa -b 4096 -f \ | |
~/.ssh/${USER}@${HOST} -N "" | |
# set ssh key on edgeos via ssh (expect) | |
expect -c 'set timeout 6 | |
proc scp { user pw host source destination } { | |
spawn scp -o StrictHostKeyChecking=no -o PreferredAuthentications=password \ | |
"$source" "$user@$host:$destination" | |
expect "word:" { | |
send "$pw\r" | |
exp_continue | |
} "100%" { | |
puts stderr "TRANSFER COMPLETED" | |
} "%" { | |
sleep 1 | |
exp_continue | |
} timeout { | |
puts stderr "SCP TIMED OUT" | |
} | |
exp_close | |
exp_wait | |
return | |
} | |
proc login_via_ssh { user pw host } { | |
global spawn_id | |
spawn ssh -o StrictHostKeyChecking=no -o PreferredAuthentications=password \ | |
$user@$host | |
expect "word:" { | |
send "$pw\r" | |
} timeout { | |
puts stderr "LOGIN VIA SSH TIMED OUT" | |
} | |
return | |
} | |
proc set_ssh_key_on_edgeos_via_ssh { user pw host key } { | |
scp "$user" "$pw" "$host" "$key" "/home/$user/.ssh/$user.pub" | |
login_via_ssh "$user" "$pw" "$host" | |
expect "\\\$" { | |
sleep 4 | |
send "configure\r" | |
expect "#" | |
send "delete system login user $user authentication public-keys\r" | |
expect "#" | |
send "commit\r" | |
expect "#" | |
send "loadkey $user /home/$user/.ssh/$user.pub\r" | |
expect "#" | |
send "exit\r" | |
expect "\\\$" | |
send "rm -- /home/$user/.ssh/$user.pub\r" | |
expect "\\\$" | |
send "exit\r" | |
} timeout { | |
puts stderr "SET SSH KEY ON EDGEOS VIA SSH TIMED OUT" | |
} | |
exp_close | |
exp_wait | |
return | |
} | |
'"set_ssh_key_on_edgeos_via_ssh ${USER} ${PW} ${HOST} ${HOME}/.ssh/${USER}@${HOST}.pub" | |
## Create the New Admin User | |
################################################################################ | |
# add user to router with admin privileges | |
ssh -i ~/.ssh/ubnt@192.168.1.1 ubnt@192.168.1.1 "${CFG} begin | |
${CFG} set system login user ${ADMIN_USER} authentication plaintext-password ${ADMIN_PW} | |
${CFG} set system login user ${ADMIN_USER} level admin | |
${CFG} commit | |
${CFG} end | |
exit" | |
# repeat steps to add ssh keys | |
rm ~/.ssh/${ADMIN_USER}@${HOST} \ | |
~/.ssh/${ADMIN_USER}@${HOST}.pub 2>/dev/null || : | |
ssh-keygen -t rsa -b 4096 -f ~/.ssh/${ADMIN_USER}@${HOST} -N "" | |
# expect scripting | |
expect -c 'set timeout 6 | |
proc scp { user pw host source destination } { | |
spawn scp -o StrictHostKeyChecking=no -o PreferredAuthentications=password \ | |
"$source" "$user@$host:$destination" | |
expect "word:" { | |
send "$pw\r" | |
exp_continue | |
} "100%" { | |
puts stderr "TRANSFER COMPLETED" | |
} "%" { | |
sleep 1 | |
exp_continue | |
} timeout { | |
puts stderr "SCP TIMED OUT" | |
} | |
exp_close | |
exp_wait | |
return | |
} | |
proc login_via_ssh { user pw host } { | |
global spawn_id | |
spawn ssh -o StrictHostKeyChecking=no -o PreferredAuthentications=password $user@$host | |
expect "word:" { | |
send "$pw\r" | |
} timeout { | |
puts stderr "LOGIN VIA SSH TIMED OUT" | |
} | |
return | |
} | |
proc set_ssh_key_on_edgeos_via_ssh { user pw host key } { | |
scp "$user" "$pw" "$host" "$key" "/home/$user/.ssh/$user.pub" | |
login_via_ssh "$user" "$pw" "$host" | |
expect "\\\$" { | |
sleep 4 | |
send "configure\r" | |
expect "#" | |
send "delete system login user $user authentication public-keys\r" | |
expect "#" | |
send "commit\r" | |
expect "#" | |
send "loadkey $user /home/$user/.ssh/$user.pub\r" | |
expect "#" | |
send "exit\r" | |
expect "\\\$" | |
send "rm -- /home/$user/.ssh/$user.pub\r" | |
expect "\\\$" | |
send "exit\r" | |
} timeout { | |
puts stderr "SET SSH KEY ON EDGEOS VIA SSH TIMED OUT" | |
} | |
exp_close | |
exp_wait | |
return | |
} | |
'"set_ssh_key_on_edgeos_via_ssh ${ADMIN_USER} ${ADMIN_PW} ${HOST} ${HOME}/.ssh/${ADMIN_USER}@${HOST}.pub" | |
# admin login shortcut | |
# need to use `SH_WORD_SPLIT` option in `zsh` | |
RRUN="ssh -o StrictHostKeyChecking=no -i ~/.ssh/tandem@192.168.1.1 ${ADMIN_USER}@192.168.1.1" | |
# remove admin password as soon as possible | |
unset ADMIN_PW | |
## Delete Default Admin User | |
################################################################################ | |
# remove default ubnt user | |
${RRUN} "${CFG} begin | |
${CFG} delete system login user ubnt | |
${CFG} commit | |
${CFG} end | |
exit" | |
# delete keys for ubnt user | |
rm ~/.ssh/ubnt@192.168.1.1 \ | |
~/.ssh/ubnt@192.168.1.1.pub | |
## Clear EULA Prompt | |
################################################################################ | |
$RRUN "sudo touch /root.dev/www/eula" | |
################################################################################ | |
### CONFIGURE LAN TO WAN CONNECTIVITY ########################################## | |
################################################################################ | |
# | |
# 1. Configure LAN DHCP | |
# 2. Discover Interfaces | |
# 3. Configure WAN Firewall | |
# 4. Configure WAN Addressing and NAT | |
# 5. Update Firmware | |
# | |
################################################################################ | |
## Configure LAN DHCP | |
################################################################################ | |
# create default dhcp service | |
${RRUN} "${CFG} begin | |
${CFG} set service dhcp-server use-dnsmasq enable | |
${CFG} set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 start 192.168.1.10 stop 192.168.1.245 | |
${CFG} commit | |
${CFG} end | |
exit" | |
## Interface Discovery | |
declare WAN_IF="" | |
declare -a LAN_IFS=() | |
declare -a UP_IFS=() | |
for UP_IF in $(${RRUN} "ip link" 2>/dev/null | grep "state UP" | awk '{ print $2 }' | sed 's/://g'); do | |
${RRUN} "${CFG} begin; ${CFG} show interfaces ethernet ${UP_IF} address; ${CFG} end" 2>/dev/null| grep -iq "dhcp" && | |
WAN_IF="${UP_IF}" || | |
LAN_IFS+=("${UP_IF}") | |
UP_IFS+=("${UP_IF}") | |
done | |
## Configure WAN Firewall | |
################################################################################ | |
# sane default wan rules | |
${RRUN} "${CFG} begin | |
${CFG} set firewall name WAN_IN default-action drop | |
${CFG} set firewall name WAN_IN description 'Incoming from WAN' | |
${CFG} set firewall name WAN_IN rule 1000 action drop | |
${CFG} set firewall name WAN_IN rule 1000 state invalid enable | |
${CFG} set firewall name WAN_IN rule 1000 description 'Drop Invalid' | |
${CFG} set firewall name WAN_IN rule 3000 action accept | |
${CFG} set firewall name WAN_IN rule 3000 state established enable | |
${CFG} set firewall name WAN_IN rule 3000 description 'Accept Established' | |
${CFG} set firewall name WAN_IN rule 3010 action accept | |
${CFG} set firewall name WAN_IN rule 3010 state related enable | |
${CFG} set firewall name WAN_IN rule 3010 description 'Accept Related' | |
${CFG} set interfaces ethernet ${WAN_IF} firewall in name WAN_IN | |
${CFG} set firewall name WAN_LOCAL default-action drop | |
${CFG} set firewall name WAN_LOCAL description 'From WAN to this Router' | |
${CFG} set firewall name WAN_LOCAL rule 1000 action drop | |
${CFG} set firewall name WAN_LOCAL rule 1000 state invalid enable | |
${CFG} set firewall name WAN_LOCAL rule 1000 description 'Drop Invalid' | |
${CFG} set firewall name WAN_LOCAL rule 2000 action accept | |
${CFG} set firewall name WAN_LOCAL rule 2000 protocol icmp | |
${CFG} set firewall name WAN_LOCAL rule 2000 icmp type-name echo-request | |
${CFG} set firewall name WAN_LOCAL rule 2000 limit rate 2/second | |
${CFG} set firewall name WAN_LOCAL rule 2000 limit burst 5 | |
${CFG} set firewall name WAN_LOCAL rule 2000 description 'Accept Echo Requests (Limited)' | |
${CFG} set firewall name WAN_LOCAL rule 2010 action drop | |
${CFG} set firewall name WAN_LOCAL rule 2010 protocol icmp | |
${CFG} set firewall name WAN_LOCAL rule 2010 icmp type-name echo-request | |
${CFG} set firewall name WAN_LOCAL rule 2010 description 'Drop Echo Requests' | |
${CFG} set firewall name WAN_LOCAL rule 3000 action accept | |
${CFG} set firewall name WAN_LOCAL rule 3000 state established enable | |
${CFG} set firewall name WAN_LOCAL rule 3000 description 'Accept Established' | |
${CFG} set firewall name WAN_LOCAL rule 3010 action accept | |
${CFG} set firewall name WAN_LOCAL rule 3010 state related enable | |
${CFG} set firewall name WAN_LOCAL rule 3010 description 'Accept Related' | |
${CFG} set interfaces ethernet ${WAN_IF} firewall local name WAN_LOCAL | |
${CFG} commit | |
${CFG} end | |
exit" | |
## Configure WAN Addressing and NAT | |
################################################################################ | |
# configure wan address, default gateway and dns | |
# skip this if your WAN address is provided via DHCP | |
${RRUN} "${CFG} begin | |
${CFG} delete interfaces ethernet ${WAN_IF} address dhcp | |
${CFG} set interfaces ethernet ${WAN_IF} address ${WAN_IP}/${WAN_SM} | |
${CFG} set interfaces ethernet ${WAN_IF} description WAN | |
${CFG} commit | |
${CFG} end | |
exit" | |
# configure gateway and NAT | |
${RRUN} "${CFG} begin | |
${CFG} set system gateway-address ${WAN_GW} | |
${CFG} set service nat rule 5000 type masquerade | |
${CFG} set service nat rule 5000 outbound-interface ${WAN_IF} | |
${CFG} set service nat rule 5000 description 'Default Gatway' | |
${CFG} set system name-server 9.9.9.9 | |
${CFG} set system name-server 149.112.112.112 | |
${CFG} commit | |
${CFG} end | |
exit" | |
## Update Firmware | |
################################################################################ | |
# save config | |
${RRUN} "${CFG} begin | |
${CFG} save | |
${CFG} end | |
exit" | |
# download firmware and reboot | |
${RRUN} "yes | ${OP} add system image ${ROUTER_FIRM} | |
${OP} reboot now | |
exit" | |
# some firmware updates require 2 reboots | |
sleep 15 | |
while ! ping -c 1 192.168.1.1; do | |
sleep 1 | |
done | |
sleep 15 | |
$RRUN "yes | ${OP} add system boot-image | |
$OP reboot now | |
exit" | |
# wait for router to come back online | |
sleep 15 | |
while ! ping -c 1 192.168.1.1; do | |
sleep 1 | |
done | |
sleep 15 | |
################################################################################ | |
### CONFIGURE NETWORK MANAGEMENT VLAN ########################################## | |
################################################################################ | |
# | |
# 1. Create NET VLAN | |
# 2. Configure Firewall | |
# 3. Configure DNS Forwarding | |
# 4. Enable Debian Repositories | |
# 5. Install TFTP Server | |
# 6. Download Switch Firmware | |
# | |
################################################################################ | |
## Create NET VLAN | |
################################################################################ | |
# create vlan | |
${RRUN} "${CFG} begin | |
${CFG} set interfaces ethernet ${LAN_IFS[0]} vif 10 | |
${CFG} set interfaces ethernet ${LAN_IFS[0]} vif 10 address 10.${SITE}.10.1/24 | |
${CFG} set interfaces ethernet ${LAN_IFS[0]} vif 10 description NET | |
${CFG} commit | |
${CFG} end | |
exit" | |
# create firewall rules | |
${RRUN} "${CFG} begin | |
${CFG} set firewall name NET_OUT default-action drop | |
${CFG} set firewall name NET_OUT description 'Outgoing to NET' | |
${CFG} set firewall name NET_OUT rule 1000 action drop | |
${CFG} set firewall name NET_OUT rule 1000 state invalid enable | |
${CFG} set firewall name NET_OUT rule 1000 description 'Drop Invalid' | |
${CFG} set firewall name NET_OUT rule 3000 action accept | |
${CFG} set firewall name NET_OUT rule 3000 state established enable | |
${CFG} set firewall name NET_OUT rule 3000 description 'Accept Established' | |
${CFG} set firewall name NET_OUT rule 3010 action accept | |
${CFG} set firewall name NET_OUT rule 3010 state related enable | |
${CFG} set firewall name NET_OUT rule 3010 description 'Accept Related' | |
${CFG} set interfaces ethernet ${LAN_IFS[0]} vif 10 firewall in name NET_OUT | |
${CFG} set firewall name NET_LOCAL default-action drop | |
${CFG} set firewall name NET_LOCAL description 'From NET to this Router' | |
${CFG} set firewall name NET_LOCAL rule 1000 action drop | |
${CFG} set firewall name NET_LOCAL rule 1000 state invalid enable | |
${CFG} set firewall name NET_LOCAL rule 1000 description 'Drop Invalid' | |
${CFG} set firewall name NET_LOCAL rule 2000 action accept | |
${CFG} set firewall name NET_LOCAL rule 2000 protocol icmp | |
${CFG} set firewall name NET_LOCAL rule 2000 icmp type-name echo-request | |
${CFG} set firewall name NET_LOCAL rule 2000 description 'Accept Echo Requests' | |
${CFG} set firewall name NET_LOCAL rule 3000 action accept | |
${CFG} set firewall name NET_LOCAL rule 3000 state established enable | |
${CFG} set firewall name NET_LOCAL rule 3000 description 'Accept Established' | |
${CFG} set firewall name NET_LOCAL rule 3010 action accept | |
${CFG} set firewall name NET_LOCAL rule 3010 state related enable | |
${CFG} set firewall name NET_LOCAL rule 3010 description 'Accept Related' | |
${CFG} set firewall name NET_LOCAL rule 4000 action accept | |
${CFG} set firewall name NET_LOCAL rule 4000 protocol udp | |
${CFG} set firewall name NET_LOCAL rule 4000 destination port ntp | |
${CFG} set firewall name NET_LOCAL rule 4000 description 'Accept NTP' | |
${CFG} set firewall name NET_LOCAL rule 4010 action accept | |
${CFG} set firewall name NET_LOCAL rule 4010 protocol udp | |
${CFG} set firewall name NET_LOCAL rule 4010 destination port 53 | |
${CFG} set firewall name NET_LOCAL rule 4010 description 'Accept DNS' | |
${CFG} set firewall name NET_LOCAL rule 4020 action accept | |
${CFG} set firewall name NET_LOCAL rule 4020 protocol udp | |
${CFG} set firewall name NET_LOCAL rule 4020 destination port 69 | |
${CFG} set firewall name NET_LOCAL rule 4020 description 'Accept TFTP' | |
${CFG} set interfaces ethernet ${LAN_IFS[0]} vif 10 firewall local name NET_LOCAL | |
${CFG} commit | |
${CFG} end | |
exit" | |
## Configuring DNS Forwarding | |
################################################################################ | |
${RRUN} "${CFG} begin | |
${CFG} set service dns forwarding cache-size 400 | |
${CFG} set service dns forwarding listen-on ${LAN_IFS[0]} | |
${CFG} set service dns forwarding listen-on ${LAN_IFS[0]}.10 | |
${CFG} set service dns forwarding system | |
${CFG} commit | |
${CFG} end | |
exit" | |
## Enable Debian Repositories | |
################################################################################ | |
${RRUN} "${CFG} begin | |
${CFG} set system package repository stretch components 'main contrib non-free' | |
${CFG} set system package repository stretch distribution stretch | |
${CFG} set system package repository stretch url http://http.us.debian.org/debian | |
${CFG} commit | |
${CFG} end | |
sudo apt-get -q update | |
exit" | |
## Install TFTP Server | |
################################################################################ | |
# this will generate some errors but does provide a functional `in.tftpd` | |
${RRUN} "sudo apt-cache -q search tftpd | |
sudo DEBIAN_FRONTEND=noninteractive apt-get -yq install tftpd-hpa | |
exit" | |
## Download Switch Firmware | |
################################################################################ | |
for FIRM in ${SWITCH_FIRMS[@]}; do | |
$RRUN "sudo curl ${FIRM} -o /srv/tftp/${FIRM##*/}" | |
done | |
################################################################################ | |
### CONFIGURE ADMIN VLAN ####################################################### | |
################################################################################ | |
# | |
# 1. Create ADMIN VLAN | |
# 2. Configure Firewall | |
# 3. | |
# 4. | |
# 5. | |
# 6. | |
# | |
################################################################################ | |
## Create ADMIN VLAN | |
################################################################################ | |
# create vlan | |
${RRUN} "${CFG} begin | |
${CFG} set interfaces ethernet ${LAN_IFS[0]} vif 20 | |
${CFG} set interfaces ethernet ${LAN_IFS[0]} vif 20 address 10.${SITE}.20.1/24 | |
${CFG} set interfaces ethernet ${LAN_IFS[0]} vif 20 description ADMIN | |
${CFG} commit | |
${CFG} end | |
exit" | |
# create firewall rules | |
${RRUN} "${CFG} begin | |
${CFG} set firewall group network-group admins description 'Administrators' | |
${CFG} set firewall group network-group admins network 10.${SITE}.20.0/24 | |
${CFG} set firewall name ADMIN_OUT default-action drop | |
${CFG} set firewall name ADMIN_OUT description 'Outgoing to ADMIN' | |
${CFG} set firewall name ADMIN_OUT rule 1000 action drop | |
${CFG} set firewall name ADMIN_OUT rule 1000 state invalid enable | |
${CFG} set firewall name ADMIN_OUT rule 1000 description 'Drop Invalid' | |
${CFG} set firewall name ADMIN_OUT rule 3000 action accept | |
${CFG} set firewall name ADMIN_OUT rule 3000 state established enable | |
${CFG} set firewall name ADMIN_OUT rule 3000 description 'Accept Established' | |
${CFG} set firewall name ADMIN_OUT rule 3010 action accept | |
${CFG} set firewall name ADMIN_OUT rule 3010 state related enable | |
${CFG} set firewall name ADMIN_OUT rule 3010 description 'Accept Related' | |
${CFG} set interfaces ethernet ${LAN_IFS[0]} vif 20 firewall in name ADMIN_OUT | |
${CFG} set firewall name ADMIN_LOCAL default-action drop | |
${CFG} set firewall name ADMIN_LOCAL description 'From ADMIN to this Router' | |
${CFG} set firewall name ADMIN_LOCAL rule 1000 action drop | |
${CFG} set firewall name ADMIN_LOCAL rule 1000 state invalid enable | |
${CFG} set firewall name ADMIN_LOCAL rule 1000 description 'Drop Invalid' | |
${CFG} set firewall name ADMIN_LOCAL rule 2000 action accept | |
${CFG} set firewall name ADMIN_LOCAL rule 2000 protocol icmp | |
${CFG} set firewall name ADMIN_LOCAL rule 2000 icmp type-name echo-request | |
${CFG} set firewall name ADMIN_LOCAL rule 2000 description 'Accept Echo Requests' | |
${CFG} set firewall name ADMIN_LOCAL rule 3000 action accept | |
${CFG} set firewall name ADMIN_LOCAL rule 3000 state established enable | |
${CFG} set firewall name ADMIN_LOCAL rule 3000 description 'Accept Established' | |
${CFG} set firewall name ADMIN_LOCAL rule 3010 action accept | |
${CFG} set firewall name ADMIN_LOCAL rule 3010 state related enable | |
${CFG} set firewall name ADMIN_LOCAL rule 3010 description 'Accept Related' | |
${CFG} set firewall name ADMIN_LOCAL rule 4000 action accept | |
${CFG} set firewall name ADMIN_LOCAL rule 4000 protocol udp | |
${CFG} set firewall name ADMIN_LOCAL rule 4000 destination port ntp | |
${CFG} set firewall name ADMIN_LOCAL rule 4000 description 'Accept NTP' | |
${CFG} set firewall name ADMIN_LOCAL rule 4010 action accept | |
${CFG} set firewall name ADMIN_LOCAL rule 4010 protocol udp | |
${CFG} set firewall name ADMIN_LOCAL rule 4010 destination port 53 | |
${CFG} set firewall name ADMIN_LOCAL rule 4010 description 'Accept DNS' | |
${CFG} set firewall name ADMIN_LOCAL rule 4020 action accept | |
${CFG} set firewall name ADMIN_LOCAL rule 4020 protocol tcp | |
${CFG} set firewall name ADMIN_LOCAL rule 4020 destination port 22 | |
${CFG} set firewall name ADMIN_LOCAL rule 4020 log enable | |
${CFG} set firewall name ADMIN_LOCAL rule 4020 description 'Accept SSH' | |
${CFG} set firewall name ADMIN_LOCAL rule 4030 action accept | |
${CFG} set firewall name ADMIN_LOCAL rule 4030 protocol tcp | |
${CFG} set firewall name ADMIN_LOCAL rule 4030 destination port 80 | |
${CFG} set firewall name ADMIN_LOCAL rule 4030 log enable | |
${CFG} set firewall name ADMIN_LOCAL rule 4030 description 'Accept HTTP' | |
${CFG} set firewall name ADMIN_LOCAL rule 4040 action accept | |
${CFG} set firewall name ADMIN_LOCAL rule 4040 protocol tcp | |
${CFG} set firewall name ADMIN_LOCAL rule 4040 destination port 443 | |
${CFG} set firewall name ADMIN_LOCAL rule 4040 log enable | |
${CFG} set firewall name ADMIN_LOCAL rule 4040 description 'Accept HTTPS' | |
${CFG} set interfaces ethernet ${LAN_IFS[0]} vif 20 firewall local name ADMIN_LOCAL | |
${CFG} set firewall name NET_OUT rule 4000 action accept | |
${CFG} set firewall name NET_OUT rule 4000 protocol all | |
${CFG} set firewall name NET_OUT rule 4000 source group Administrators | |
${CFG} set firewall name NET_OUT rule 4000 log enable | |
${CFG} set firewall name NET_OUT rule 4000 description 'Accept Admin' | |
${CFG} commit | |
${CFG} end | |
exit" | |
################################################################################ | |
### DISCOVER SWITCHES ########################################################## | |
################################################################################ | |
# | |
# 1. Discover Ubiquiti Devices | |
# 2. Identify Edgeswitches | |
# | |
################################################################################ | |
## Discover Ubiquiti Devices | |
################################################################################ | |
# track ubiquiti devices and edgeswitches specifically | |
declare -a UBNT_DEVS=() | |
declare -a EDGE_SWITCHES=() | |
# find ubiquiti devices by oui | |
for OUI in $(curl http://standards-oui.ieee.org/oui.txt 2>/dev/null | | |
grep -i "ubiquiti" | | |
grep "(hex)" | | |
awk '{ print $1 }' | | |
sed 's/-/:/g' | | |
tr '\n' ' '); do | |
# correlate to dhcp leases | |
for DEV in $(${RRUN} "${OP} show dhcp leases" 2>/dev/null | | |
grep -i "${OUI}" | | |
grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}' | | |
tr '\n' ' ' ); do | |
UBNT_DEVS+=("${DEV}") | |
done | |
done | |
# sort ubiquiti devices | |
declare -a SORTED_UBNT_DEVS=() | |
while read SORTED_UBNT_DEV; do | |
SORTED_UBNT_DEVS+=("${SORTED_UBNT_DEV}") | |
done <<< "$(for UBNT_DEV in ${UBNT_DEVS[@]}; do echo "${UBNT_DEV}"; done | sort | uniq)" | |
## Identify Edgeswitches | |
################################################################################ | |
# scrape web gui to confirm edgeswitch | |
for IP in ${UBNT_DEVS[@]}; do | |
{ curl -kv "https://${IP}/" 2>&1 | | |
grep -iq edgeswitch || #new ui | |
curl -kv "http://${IP}/htdocs/login/login.lsp" 2>&1 | | |
grep -iq edgeos || #old ui | |
curl -kv "https://${IP}/htdocs/login/login.lsp" 2>&1 | | |
grep -iq edgeos #old ui https | |
} && EDGE_SWITCHES+=("${IP}") | |
done | |
# sort edgeswitches | |
declare -a SORTED_EDGE_SWITCHES=() | |
while read SORTED_EDGE_SWITCH; do | |
SORTED_EDGE_SWITCHES+=("${SORTED_EDGE_SWITCH}") | |
done <<< "$(for EDGE_SWITCH in ${EDGE_SWITCHES[@]}; do echo "${EDGE_SWITCH}"; done | sort | uniq)" | |
echo "############################################################################" >&2 | |
echo "# DEVICES DISCOVERED #######################################################" >&2 | |
echo "############################################################################" >&2 | |
echo "# ALL DISCOVERED UBNT DEVICES" >&2 | |
echo "# ${UBNT_DEVS[@]}" >&2 | |
echo "############################################################################" >&2 | |
echo "# ALL DISCOVERED SWITCHES" >&2 | |
echo "# ${EDGE_SWITCHES[@]}" >&2 | |
echo "############################################################################" >&2 | |
################################################################################ | |
### ONBOARD SWITCHES ########################################################### | |
################################################################################ | |
# | |
# For Each Switch | |
# | |
# 1. Enable SSH via Telnet | |
# 2. Correlate Firmware | |
# 3. Update Firmware | |
# | |
################################################################################ | |
# | |
# Either Telnet or SSH needs to be configured on the switch. I have not yet | |
# developed a cURL hack to enable SSH on the Edgeswitches. | |
# | |
################################################################################ | |
## Loop Through Switches | |
################################################################################ | |
# track configured switches, we may discover new switches as 24v POE devices are | |
# discovered | |
declare -a CONFIGURED_SWITCHES=() | |
while [ -z "${CONFIGURED_SWITCHES-}" ] || | |
[ "${#CONFIGURED_SWITCHES[@]}" -ne "${#SORTED_EDGE_SWITCHES[@]}" ]; do | |
for SWITCH in ${SORTED_EDGE_SWITCHES[@]}; do | |
if [[ ! "${CONFIGURED_SWITCHES-}" =~ "${SWITCH}" ]]; then | |
## Enable SSH via Telnet | |
########################################################################## | |
expect -c 'set timeout 6 | |
proc login_to_edgeswitch_via_telnet { user pw host } { | |
global spawn_id | |
spawn telnet $host | |
expect "Escape character is" { | |
expect "ser:" | |
send "$user\r" | |
expect "word:" | |
send "$pw\r" | |
expect ">" { | |
send "enable\r" | |
expect "word:" { | |
send "$pw\r" | |
} "#" { | |
send "\r" | |
} | |
} "#" { | |
send "\r" | |
} | |
} timeout { | |
puts stderr "LOGIN TO EDGESWITCH VIA TELNET TIMED OUT" | |
} | |
return | |
} | |
proc set_ssh_on_edgeswitch_via_telnet { user pw host } { | |
login_to_edgeswitch_via_telnet "$user" "$pw" "$host" | |
expect "#" { | |
send "configure\r" | |
expect "(Config)#" { | |
send "crypto key generate rsa\r" | |
sleep 1 | |
exp_continue | |
} "N] :" { | |
send "n" | |
} | |
expect "(Config)#" { | |
send "crypto key generate dsa\r" | |
sleep 1 | |
exp_continue | |
} "N] :" { | |
send "n" | |
} | |
expect "(Config)#" | |
send "exit\r" | |
expect "#" | |
send "write memory\r" | |
expect "(y/n)" | |
send "y" | |
expect "#" | |
send "ip ssh protocol 2\r" | |
expect "#" | |
send "ip ssh server enable\r" | |
expect "#" | |
send "sshcon maxsessions 2\r" | |
expect "#" | |
send "sshcon timeout 5\r" | |
expect "#" | |
send "write memory\r" | |
expect "(y/n)" | |
send "y" | |
expect "#" | |
send "reload\r" | |
expect "(y/n)" | |
send "y" | |
send \033 | |
expect "telnet>" | |
send "quit" | |
} timeout { | |
puts stderr "SET SSH ON EDGESWITCH VIA TELNET TIMED OUT" | |
} | |
exp_close | |
exp_wait | |
return | |
} | |
'"set_ssh_on_edgeswitch_via_telnet ubnt ubnt ${SWITCH}" | | |
grep -iq "Configuration Saved" && | |
# wait for switch to come back online | |
sleep 15 && | |
while ! ping -c 1 ${SWITCH}; do | |
sleep 1 | |
done && | |
sleep 10 || : | |
## Correlate Firmware | |
########################################################################## | |
declare CORRECT_FIRM="" | |
declare FIRM_PRE=$(expect -c ' set timeout 6 | |
proc login_to_edgeswitch_via_ssh { user pw host } { | |
global spawn_id | |
spawn ssh -o StrictHostKeyChecking=no -o PreferredAuthentications=password $user@$host | |
expect "name:" { | |
send "$user\r" | |
exp_continue | |
} "word:" { | |
send "$pw\r" | |
} | |
expect ">" { | |
send "enable\r" | |
expect "word:" { | |
send "$pw\r" | |
} "#" { | |
send "\r" | |
} | |
} "#" { | |
send "\r" | |
} timeout { | |
puts stderr "LOGIN TO EDGESWITCH VIA SSH TIMED OUT" | |
} | |
return | |
} | |
proc get_info_on_edgeswitch_via_ssh { user pw host } { | |
login_to_edgeswitch_via_ssh "$user" "$pw" "$host" | |
expect "#" { | |
send "show hardware\r" | |
expect "#" | |
send "show sysinfo\r" | |
expect "#" | |
send "show version\r" | |
expect "#" | |
send "show platform vpd\r" | |
expect "#" | |
send "show bootvar\r" | |
expect "#" | |
send "show environment\r" | |
expect "#" | |
send "show info\r" | |
expect "#" | |
send "exit\r" | |
expect ">" | |
send "quit" | |
} timeout { | |
puts stderr "GET INFO ON EDGESWITCH VIA SSH TIMED OUT" | |
} | |
} | |
'"get_info_on_edgeswitch_via_ssh ubnt ubnt ${SWITCH}" | | |
sed 's/System Name.*EdgeSwitch X/file name esx.0/' | | |
grep -i "file name" | | |
awk '{ print $NF }' | | |
cut -d '.' -f 1) | |
[ "${FIRM_PRE}" == "ES48" ] && | |
FIRM_PRE="eswh" || : | |
for FIRM in ${SWITCH_FIRMS[@]}; do | |
echo "${FIRM##*/}" | | |
cut -d '.' -f 1 | | |
grep -iq "${FIRM_PRE}" && | |
CORRECT_FIRM="${FIRM##*/}" | |
done | |
## Update Firmware | |
########################################################################## | |
${RRUN} "sudo killall in.tftpd" || : | |
${RRUN} "sudo in.tftpd -l -a 192.168.1.1:69 -s /srv/tftp" | |
expect -c 'set timeout 6 | |
proc login_to_edgeswitch_via_ssh { user pw host } { | |
global spawn_id | |
spawn ssh -o StrictHostKeyChecking=no -o PreferredAuthentications=password $user@$host | |
expect "name:" { | |
send "$user\r" | |
exp_continue | |
} "word:" { | |
send "$pw\r" | |
} | |
expect ">" { | |
send "enable\r" | |
expect "word:" { | |
send "$pw\r" | |
} "#" { | |
send "\r" | |
} | |
} "#" { | |
send "\r" | |
} timeout { | |
puts stderr "LOGIN TO EDGESWITCH VIA SSH TIMED OUT" | |
} | |
return | |
} | |
proc set_firmware_on_edgeswitch_via_ssh { user pw host firm } { | |
login_to_edgeswitch_via_ssh "$user" "$pw" "$host" | |
expect " #" { | |
send "copy tftp://192.168.1.1/$firm backup\r" | |
expect "(y/n)" | |
send "y" | |
expect "transfer starting" { | |
set timeout 600 | |
} | |
expect "#" | |
set timeout 30 | |
send "boot system backup\r" | |
expect "#" | |
set timeout 6 | |
send "reload\r" | |
expect "(y/n)" | |
send "y\r" | |
send \033 | |
} timeout { | |
puts stderr "SET FIRMWARE ON EDGESWITCH VIA SSH TIMED OUT" | |
} | |
exp_close | |
exp_wait | |
return | |
} | |
'"set_firmware_on_edgeswitch_via_ssh ubnt ubnt ${SWITCH} ${CORRECT_FIRM}" | |
${RRUN} "sudo killall in.tftpd" | |
# wait for switch to come back online | |
sleep 15 | |
while ! ping -c 1 ${SWITCH}; do | |
sleep 1 | |
done | |
sleep 10 | |
echo "${CORRECT_FIRM}" | grep -iq "eswh" && | |
{ | |
## Test 24V on Interfaces with Open Status (Media Present but No Signal) | |
######################################################################## | |
# WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! | |
# THIS CAN DAMAGE YOUR HARDWARE | |
# YOU PROBABLY SHOULDN'T DO IT! | |
# WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! | |
######################################################################## | |
expect -c 'set timeout 6 | |
proc login_to_edgeswitch_via_ssh { user pw host } { | |
global spawn_id | |
spawn ssh -o StrictHostKeyChecking=no -o PreferredAuthentications=password $user@$host | |
expect "name:" { | |
send "$user\r" | |
exp_continue | |
} "word:" { | |
send "$pw\r" | |
} | |
expect ">" { | |
send "enable\r" | |
expect "word:" { | |
send "$pw\r" | |
} "#" { | |
send "\r" | |
} | |
} "#" { | |
send "\r" | |
} timeout { | |
puts stderr "LOGIN TO EDGESWITCH VIA SSH TIMED OUT" | |
} | |
return | |
} | |
proc test_poe_24v_on_open_interfaces_on_edgeswitch_via_ssh { user pw host } { | |
login_to_edgeswitch_via_ssh "$user" "$pw" "$host" | |
set iface 0 | |
expect "interface does not exist" { | |
expect "#" | |
send "exit\r" | |
expect ">" | |
send "exit\r" | |
} ".. Open" { | |
send "configure\r" | |
expect "(Config)#" | |
send "interface 0/$iface\r" | |
expect "(Interface 0/$iface)#" | |
puts stderr "" | |
puts stderr "" | |
puts stderr "WARNING: ENABLING 24V POE ON INTERFACE 0/$iface" | |
puts stderr "24V POE CAN DAMAGE INCOMPATIBLE HARDWARE" | |
puts stderr "YOU HAVE 10 SECONDS TO ABORT VIA CTRL-C" | |
puts stderr "" | |
puts stderr "" | |
send "\r" | |
expect "#" | |
sleep 10 | |
send "poe opmode passive24v\r" | |
expect "nvalid input detected" { | |
puts stderr "" | |
puts stderr "24V POE NOT SUPPORTED ON INTERFACE 0/$iface" | |
puts stderr "" | |
expect "#" | |
send "\r" | |
} "(y/n)" { | |
send "y\r" | |
expect "(Interface 0/$iface)#" | |
send "exit\r" | |
expect "(Config)#" | |
send "exit\r" | |
expect "#" | |
sleep 30 | |
send "show mac-addr-table\r" | |
sleep 2 | |
set timeout 2 | |
expect "0/$iface" { | |
puts stderr "" | |
puts stderr "24V POE DEVICE DETECTED ON INTERFACE 0/$iface" | |
puts stderr "" | |
expect "#" | |
send "\r" | |
} timeout { | |
send "configure\r" | |
expect "(Config)#" | |
send "interface 0/$iface\r" | |
expect "(Interface 0/$iface)#" | |
puts stderr "" | |
puts stderr "NO 24V POE DEVICE DETECTED ON INTERFACE 0/$iface" | |
puts stderr "DISABLING 24V POE ON INTERFACE 0/$iface" | |
puts stderr "" | |
send "\r" | |
expect "(Interface 0/$iface)#" | |
send "poe opmode auto\r" | |
expect "(Interface 0/$iface)#" | |
send "exit\r" | |
expect "(Config)#" | |
send "exit\r" | |
} | |
} | |
set timeout 6 | |
exp_continue | |
} "#" { | |
set timeout 15 | |
set iface [expr {$iface + 1}] | |
send "cablestatus 0/$iface\r" | |
exp_continue | |
} timeout { | |
puts stderr "TEST POE 24V ON OPEN INTERFACES ON EDGESWITCH VIA SSH" | |
} | |
exp_close | |
exp_wait | |
return | |
} | |
'"test_poe_24v_on_open_interfaces_on_edgeswitch_via_ssh ubnt ubnt ${SWITCH}" | |
} | |
echo "${CORRECT_FIRM}" | grep -iq "esx" && | |
{ | |
expect -c 'set timeout 6 | |
proc login_to_edgeswitch_via_ssh { user pw host } { | |
global spawn_id | |
spawn ssh -o StrictHostKeyChecking=no -o PreferredAuthentications=password $user@$host | |
expect "name:" { | |
send "$user\r" | |
exp_continue | |
} "word:" { | |
send "$pw\r" | |
} | |
expect ">" { | |
send "enable\r" | |
expect "word:" { | |
send "$pw\r" | |
} "#" { | |
send "\r" | |
} | |
} "#" { | |
send "\r" | |
} timeout { | |
puts stderr "LOGIN TO EDGESWITCH VIA SSH TIMED OUT" | |
} | |
return | |
} | |
proc set_poe_24v_on_interface_8_on_edgeswitch_esx_via_ssh { user pw host } { | |
login_to_edgeswitch_via_ssh "$user" "$pw" "$host" | |
expect "#" { | |
send "configure\r" | |
expect "#" | |
send "interface GigabitEthernet 8\r" | |
expect "#" | |
send "?" | |
expect "poe-passive24v" { | |
expect "#" | |
puts stderr "" | |
puts stderr "" | |
puts stderr "WARNING: ENABLING 24V POE ON INTERFACE 8" | |
puts stderr "24V POE CAN DAMAGE INCOMPATIBLE HARDWARE" | |
puts stderr "YOU HAVE 10 SECONDS TO ABORT VIA CTRL-C" | |
puts stderr "" | |
puts stderr "" | |
send "\r" | |
expect "#" | |
sleep 10 | |
send "poe-passive24v\r" | |
} "#" { | |
puts stderr "" | |
puts stderr "24V POE NOT SUPPORTED ON INTERFACE 8" | |
puts stderr "" | |
} | |
expect "#" { | |
send "exit\r" | |
exp_continue | |
} ">" { | |
send "exit\r" | |
} | |
} | |
} | |
'"set_poe_24v_on_interface_8_on_edgeswitch_esx_via_ssh ubnt ubnt ${SWITCH}" | |
} | |
## Discover Ubiquiti Devices | |
################################################################################ | |
# track ubiquiti devices and edgeswitches specifically | |
declare -a UBNT_DEVS=() | |
declare -a EDGE_SWITCHES=() | |
# find ubiquiti devices by oui | |
for OUI in $(curl http://standards-oui.ieee.org/oui.txt 2>/dev/null | | |
grep -i "ubiquiti" | | |
grep "(hex)" | | |
awk '{ print $1 }' | | |
sed 's/-/:/g' | | |
tr '\n' ' '); do | |
# correlate to dhcp leases | |
for DEV in $(${RRUN} "${OP} show dhcp leases" 2>/dev/null | | |
grep -i "${OUI}" | | |
grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}' | | |
tr '\n' ' ' ); do | |
UBNT_DEVS+=("${DEV}") | |
done | |
done | |
# sort ubiquiti devices | |
declare -a SORTED_UBNT_DEVS=() | |
while read SORTED_UBNT_DEV; do | |
SORTED_UBNT_DEVS+=("${SORTED_UBNT_DEV}") | |
done <<< "$(for UBNT_DEV in ${UBNT_DEVS[@]}; do echo "${UBNT_DEV}"; done | sort | uniq)" | |
## Identify Edgeswitches | |
################################################################################ | |
# scrape web gui to confirm edgeswitch | |
for IP in ${UBNT_DEVS[@]}; do | |
{ curl -kv "https://${IP}/" 2>&1 | | |
grep -iq edgeswitch || #new ui | |
curl -kv "http://${IP}/htdocs/login/login.lsp" 2>&1 | | |
grep -iq edgeos || #old ui | |
curl -kv "https://${IP}/htdocs/login/login.lsp" 2>&1 | | |
grep -iq edgeos #old ui https | |
} && EDGE_SWITCHES+=("${IP}") | |
done | |
# sort edgeswitches | |
declare -a SORTED_EDGE_SWITCHES=() | |
while read SORTED_EDGE_SWITCH; do | |
SORTED_EDGE_SWITCHES+=("${SORTED_EDGE_SWITCH}") | |
done <<< "$(for EDGE_SWITCH in ${EDGE_SWITCHES[@]}; do echo "${EDGE_SWITCH}"; done | sort | uniq)" | |
# switch configured | |
CONFIGURED_SWITCHES+=("${SWITCH}") | |
echo "############################################################################" >&2 | |
echo "# SWITCH CONFIGURED ########################################################" >&2 | |
echo "############################################################################" >&2 | |
echo "# IP=${SWITCH}" >&2 | |
echo "# ALL DISCOVERED SWITCHES" >&2 | |
echo "# ${SORTED_EDGE_SWITCHES[@]}" >&2 | |
echo "# ALL CONFIGURED SWITCHES" >&2 | |
echo "# ${CONFIGURED_SWITCHES[@]}" >&2 | |
echo "############################################################################" >&2 | |
sleep 5 | |
fi | |
done | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment