Skip to content

Instantly share code, notes, and snippets.

@o0-o
Last active November 15, 2019 08:35
Show Gist options
  • Save o0-o/9059e61b02f511d16d1cebf392bfd81d to your computer and use it in GitHub Desktop.
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.
### 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