#!/usr/bin/env bash ## a basic script for building openwrt images for ## the TPLink Archer C7 v2 on ubuntu 20.04 ## install all dependencies before running # $ sudo apt install -y subversion g++ zlib1g-dev build-essential git python rsync man-db gawk libncurses5-dev gettext unzip file libssl-dev wget zip time ## recovery instructions: # set up tftpd server listening on 192.168.0.66 serving ArcherC7v2_tp_recovery.bin (stripped, non-boot) # available at https://cdn.seedno.de/misc/ArcherC7v2_tp_recovery.bin # plug ethernet cable into LAN1 on Archer C7, unplugging any cable in WAN port # power up router, then immediately press and hold the WPS/Reset button until the WPS light turns on # wait ~2 minutes for router to complete reset ## interfaces # eth0 - WAN # eth1 - LAN (bridged) # LAN - LAN bridge # wlan0 - 5GHz WiFi # wlan1 - 2.4GHz WiFi ## switch0 ports # Port 0: LAN CPU(?) # Port 1: WAN # Port 2: LAN 1 # Port 3: LAN 2 # Port 4: LAN 3 # Port 5: LAN 4 # Port 6: WAN CPU(?) ## front leds, from left to right # tp-link:green:power (indicates system is powered on) # tp-link:green:system (flashes when system is booting or upgrading) # tp-link:green:wlan2g (indicates whether 2.4ghz is active) # tp-link:green:wlan5g (indicates whether 5ghz is active) # tp-link:green:qss (uncertain) ## rear lcds, from top to bottom # tp-link:green:usb1 (indicates whether usb port 1 is in use) # tp-link:green:usb2 (indicates whether usb port 2 is in use) # fail in a sane manner set -eo pipefail # make sure the correct number of arguments are passed; if not, output syntax and exit if [ "$#" -ne 0 ]; then echo -e "\nUsage: openwrtimagebuilder\n" exit 1 fi # set hostname to first argument hostname="openwrt" # set base directory basedir="$(pwd)/$hostname" # set logfile location logfile="$basedir/build-$(date +%Y%m%d%H%M%S).log" # set imagebuilder directory imagebuilderdir="$basedir/imagebuilder" # set OpenWRT imagebuilder version to use release="19.07.4" target="ath79" profile="tplink_archer-c7-v2" version="openwrt-imagebuilder-$release-$target-generic.Linux-x86_64" tarball="https://downloads.openwrt.org/releases/$release/targets/$target/generic/$version.tar.xz" # delete any old builds if they exist if [ -d "$imagebuilderdir/$version" ]; then echo -e "\nRemoving old imagebuilder files..." >> "$logfile" 2>&1 rm -rf "$imagebuilderdir/$version" fi # create base directory for account mkdir -p "$imagebuilderdir" # display log location echo -e "\nLogging all build output to $logfile" # display git commit hash echo -e "\nBuilding from commit $(git rev-parse HEAD)." >> "$logfile" 2>&1 # prepend timestamp to logfile echo -e "\nBuild began at $(date +%Y/%m/%d-%H:%M).\n" >> "$logfile" 2>&1 # wrap the script into a function for logging purposes { # display imagebuilder version echo "Imagebuilder version set to $version" # display imagebuilder directory echo "Imagebuilder directory is $imagebuilderdir" # set and display working directory workdir="$imagebuilderdir/$version" echo "Working directory is $workdir" # download and extract the openwrt imagebuilder tool echo "Downloading imagebuilder tarball..." mkdir -p "$imagebuilderdir" curl -s "$tarball" | tar -xJf - -C "$imagebuilderdir" echo "Imagebuilder downloaded." # create directory for file overrides; this will serve as the effective / for any overwriting files # i.e. files/etc/dropbear/authorized_keys will be located at /etc/dropbear/authorized_keys in the final squashfs image echo -e "\nCreating required directories..." mkdir -p "$workdir"/files/etc/config mkdir -p "$workdir"/files/etc/hotplug.d/iface mkdir -p "$workdir"/files/etc/init.d mkdir -p "$workdir"/files/etc/rc.button # finished creating directories echo -e "Finished creating directories.\n" # begin generating config files echo -e "\nGenerating system config files." # set login credentials echo -e "\nBegin login credentials." cat <<'EOL' | tee "$workdir"/files/etc/shadow root:$1$Bi5SZzpW$o3ymak7u35zX.fuuGCjt2.:18396:0:99999:7::: daemon:*:0:0:99999:7::: ftp:*:0:0:99999:7::: network:*:0:0:99999:7::: nobody:*:0:0:99999:7::: dnsmasq:x:0:0:99999:7::: EOL echo -e "End login credentials.\n" # configure shell echo -e "\nBegin shell config." cat <<'EOL' | tee "$workdir"/files/etc/profile #!/bin/sh [ -e /tmp/.failsafe ] && export FAILSAFE=1 [ -f /etc/banner ] && cat /etc/banner [ -n "$FAILSAFE" ] && cat /etc/banner.failsafe fgrep -sq '/ overlay ro,' /proc/mounts && { echo 'Your JFFS2-partition seems full and overlayfs is mounted read-only.' echo 'Please try to remove files from /overlay/upper/... and reboot!' } export PATH="/usr/sbin:/usr/bin:/sbin:/bin" export HOME=$(grep -e "^${USER:-root}:" /etc/passwd | cut -d ":" -f 6) export HOME=${HOME:-/root} export PS1='\[\e[1;32m\][\[\e[1;37m\]\u@\h \[\e[1;35m\]\w\[\e[1;32m\]]\[\e[1;31m\]\\$\[\e[m\] ' case "$TERM" in xterm*|rxvt*) export PS1='\[\e]0;\u@\h: \w\a\]'$PS1 ;; esac [ -x /bin/more ] || alias more=less [ -x /usr/bin/vim ] && alias vi=vim || alias vim=vi alias ll='ls -alF --color=auto' [ -z "$KSH_VERSION" -o \! -s /etc/mkshrc ] || . /etc/mkshrc [ -x /usr/bin/arp -o -x /sbin/arp ] || arp() { cat /proc/net/arp; } [ -x /usr/bin/ldd ] || ldd() { LD_TRACE_LOADED_OBJECTS=1 $*; } [ -n "$FAILSAFE" ] || { for FILE in /etc/profile.d/*.sh; do [ -e "$FILE" ] && . "$FILE" done unset FILE } if ( grep -qs '^root::' /etc/shadow && \ [ -z "$FAILSAFE" ] ) then cat << EOF === WARNING! ===================================== There is no root password defined on this device! Use the "passwd" command to set up a new password in order to prevent unauthorized SSH logins. -------------------------------------------------- EOF fi service() { [ -f "/etc/init.d/$1" ] || { echo "service "'"'"$1"'"'" not found, the following services are available:" ls "/etc/init.d" return 1 } /etc/init.d/$@ } EOL echo -e "End shell config.\n" # create dnsmasq configs and disable win2k filtering (which breaks jabber/xmpp) echo -e "\nBegin dnsmasq config." cat <<'EOL' | tee "$workdir"/files/etc/config/dhcp config dnsmasq option domainneeded '1' option localise_queries '1' option rebind_protection '1' option rebind_localhost '1' option local '/lan/' option domain 'lan' option expandhosts '1' option authoritative '1' option readethers '1' option leasefile '/tmp/dhcp.leases' option resolvfile '/tmp/resolv.conf.auto' option localservice '1' option nonwildcard '0' option filterwin2k '0' option nonegcache '1' option sequential_ip '1' config dhcp 'LAN' option interface 'LAN' option start '100' option limit '150' option leasetime '24h' option dhcpv6 'disabled' config dhcp 'WAN' option interface 'WAN' option ignore '1' config odhcpd 'odhcpd' option maindhcp '0' option leasefile '/tmp/hosts/odhcpd' option leasetrigger '/usr/sbin/odhcpd-update' EOL echo -e "End dnsmasq config.\n" # set default firewall policy to drop inbound on wan, and allow all on lan echo -e "\nBegin firewall config." cat <<'EOL' | tee "$workdir"/files/etc/config/firewall config defaults option syn_flood '1' option input 'REJECT' option output 'ACCEPT' option forward 'REJECT' option flow_offloading '1' option flow_offloading_hw '1' config zone option name 'LAN' list network 'LAN' option input 'ACCEPT' option output 'ACCEPT' option forward 'ACCEPT' config zone option name 'WAN' list network 'WAN' option input 'REJECT' option output 'ACCEPT' option forward 'REJECT' option masq '1' option mtu_fix '1' config forwarding option src 'LAN' option dest 'WAN' config rule option name 'Allow ping' option src 'wan' option proto 'icmp' option icmp_type 'echo-request' option family 'ipv4' option target 'ACCEPT' EOL echo -e "End firewall config.\n" # set ssh listen port to tcp/9022 echo -e "\nBegin dropbear config." cat <<'EOL' | tee "$workdir"/files/etc/config/dropbear config dropbear option PasswordAuth 'on' option Port '22' EOL echo -e "End dropbear config.\n" # set up a uhttpd instance listening on 443/tcp echo -e "\nBegin uhttpd config." cat <<'EOL' | tee "$workdir"/files/etc/config/uhttpd config uhttpd 'luci' list listen_http '0.0.0.0:80' list listen_https '0.0.0.0:443' option redirect_https '1' option home '/www' option rfc1918_filter '1' option max_requests '3' option max_connections '100' option cert '/etc/uhttpd.crt' option key '/etc/uhttpd.key' option cgi_prefix '/cgi-bin' option script_timeout '60' option network_timeout '30' option http_keepalive '20' option tcp_keepalive '1' option ubus_prefix '/ubus' list interpreter ".php=/usr/bin/php-cgi" config cert 'px5g' option days '3650' option bits '1024' option country 'US' option state 'Minnesota' option location 'Minneapolis' option commonname 'OpenWRT' EOL echo -e "End uhttp config.\n" # set hostname, timezone, and other system info echo -e "\nBegin system config." cat <&1 | tee -a "$logfile" >/dev/null # append timestamp to logfile echo -e "Finished building OpenWRT image.\n\nBuild finished at $(date +%Y/%m/%d-%H:%M).\n" >> "$logfile" # display build completion status echo -e "Build complete!\n"