IX2412

From Hackerspace ACKspace
Jump to: navigation, search
Project: IX2412
Featured: Yes
State Active
Members Xopr
GitHub No GitHub project defined. Add your project here.
Description IXON IXrouter3 4G "cloud" modem
Picture
No project picture! Fill in form Picture or Upload a jpeg here

Has a

  • Mediatek MT7621AT
  • 8GB SD card
  • Winbond 25Q128JVSM 128Mbit serial flash
  • USB2512B USB2.0 hub
  • U-blox LILY-W131 wifi 2.4GHz, based on Marvell Avastor 88w8801
  • Quectel EC25-E (Main, DIV, GNSS)


Power (over Ethernet) compatibility:
barrel plug: none 24V

straight crosslink
802.3af yes unknown
legacy unknown unknown
compatible unknown unknown
Unifi unknown unknown

Note: has a 4p pluggable terminal block 12-24V

connecting UART

  • use 3.3V logic to be safe

Run terminal client in 56k 8N1: minicom -D/dev/ttyUSB0 -b57600 -os And make sure Hardware Flow Control is off: choose Serial port setup, f (to open the configuration menu, press Ctrl+a, o)

Uboot env

After pressing space to interrupt (within 1 second) you get:

Please choose the operation: 
   0: Load system code then write to Flash via Serial.
   1: Load system code to SDRAM via TFTP.
   2: Load system code then write to Flash via TFTP.
   3: Boot system code via Flash (default).
   4: Enter boot command line interface.
   7: Load U-Boot code then write to Flash via Serial.
   8: System Load UBoot to SDRAM via TFTP. (hidden in menu)
   9: Load U-Boot code then write to Flash via TFTP.

in the command line interface (4), you can continue booting with bootm bc050000

MT7621 # printenv
bootcmd=tftp
bootdelay=1
baudrate=(57600)
ethaddr="AA:BB:CC:DD:EE:FF"
ipaddr=192.168.1.1
serverip=192.168.1.2
stdin=serial
stdout=serial
stderr=serial

root password

The short answer is: it's on a "factory" partition in the flash, most likely located at 40000HEX.

How to get root without copying the flash (only using serial):

  • within the boot sequence at 3/4 of the log: search for "factory", most likely it reads something like:

[ 2.290000] 0x000000040000-0x000000050000 : "factory"

  • remember 40000HEX (and add 20DEC so it becomes 40014HEX
  • reboot (either press and hold the reset button >4s or pulse X2 pin 2 and 7
  • press space in the serial monitor (you have 1 second if it says Press space to enter the bootloader... ).
  • press 4
  • and type spi read 40014 10
    • it will return something like this:
    read len: 16
    38 4d 6d 42 52 32 35 6d 73 6d 0 0 0 0 0 0
  • use an online converter or run this in a javascript console:
    "38 4d 6d 42 52 32 35 6d 73 6d 0 0 0 0 0 0".split(" ").filter(n=>n!=="0").map(n=>String.fromCharCode(parseInt(n,16))).join("")

You can also retrieve it from the bin file: dd bs=1 skip=$((0x40000+20)) count=10 if=ixrouter.bin 2>/dev/null | tr -d '\000'


Oh by the way, it's 8MmBR25msm

pins and connectors

X2

Labeled. located near reset button, 3.3v logic.

  1. GND
  2. RX
  3. TX

X3

For programming/reading the SPI flash chip. Note that soldering a straight header will conflict with a SOIC clamp.

  1. VCC
  2. RST
  3. CLK
  4. DI
  5. DO
  6. CS
  7. GND

To reset, connect pin 2 and 7 with a small resistor (used 180Ω)

open ports

PORT     STATE SERVICE
22/tcp   open  ssh
53/tcp   open  domain
9230/tcp open  unknown

firmware image

extraction

Used minipro on a TL866II+ with 8 pin SOIC clamp while keeping the board in reset (connecting X2 pin 2 and 7)

$ minipro -p W25Q128JV@SOIC8 -r ixrouter.bin --vcc=3.3 -y
Found TL866II+ 04.2.86 (0x256)
Warning: Firmware is out of date.
  Expected  04.2.128 (0x280)
  Found     04.2.86 (0x256)
WARNING: Chip ID mismatch: expected 0xEF4018, got 0xEF7018 (unknown)
Reading Code...  27.08Sec  OK

file information

To extract the image parts, you need sasquatch and jefferson additional to binwalk, see: binwalk dependencies

$ binwalk --signature --term ixrouter.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------------------------------
78080         0x13100         U-Boot version string, "U-Boot 1.1.3 (Dec 21 2017 - 10:47:42)"
327680        0x50000         uImage header, header size: 64 bytes, header CRC: 0x4DD3DDDF, created:
                              2018-08-07 13:36:39, image size: 1213865 bytes, Data Address:
                              0x80001000, Entry Point: 0x80001000, data CRC: 0x82EB32CA, OS: Linux,
                              CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image
                              name: "MIPS OpenWrt Linux-3.18.75"
327744        0x50040         LZMA compressed data, properties: 0x6D, dictionary size: 8388608 bytes,
                              uncompressed size: 3663424 bytes
1541609       0x1785E9        Squashfs filesystem, little endian, version 4.0, compression:xz, size:
                              6334418 bytes, 1478 inodes, blocksize: 262144 bytes, created: 2018-08-07
                              13:36:44
7929856       0x790000        JFFS2 filesystem, little endian

Note that xopr used mtd-utils but jffs2reader gives an Unsupported compression method! error.

generated config file

The config file, to be generated online and put on a stick looks roughly like this:

# Router configuration
# Generated by Xosperois Dimitri for ACKspace on Mon Jan 1 1900

ixrouter.wan.3g_apn={auto|MyApn}
ixrouter.wan.3g_pincode=[1234]
ixrouter.wan.3g_mtu={1200|1499}

ixrouter.wan.ip_use_dhcp={true|false}
ixrouter.wan.ip_address=[192.168.42.100]
ixrouter.wan.ip_netmask=[255.255.255.0]
ixrouter.wan.ip_gateway=[192.168.42.1]

[ixrouter.wan.dns_server=8.8.4.4]
[ixrouter.wan.dns_server=1.1.1.1]

ixrouter.wan.digital_input_mode=[disable_vpn_low]

ixrouter.wan.http_proxy_address=[10.0.0.1]
ixrouter.wan.http_proxy_port=[6667]
ixrouter.wan.http_proxy_authentication=[basic]
ixrouter.wan.http_proxy_username=[proxyuser]
ixrouter.wan.http_proxy_password=[6667]

ixrouter.wan.wlan_ssid=[publicwifi]
ixrouter.wan.wlan_key=[myfipassword]

ixrouter.wan.ixapi_entry_point=https://ixsec-api.ixon.net:443/
ixrouter.wan.ixapi_account_id=nnnn-nnnn-nnnn-nnnn-nnnn

ixrouter.lan.gateway_less_routing=true

ixrouter.lan.ip_address=192.168.140.1

convert to regular (4G) router

you need:

  • IXrouter3
  • mini (the regular) SIM card without an active pin code

steps:

  • make it a fresh install, login and type:
    either firstboot -y && reboot now (soft factory reset)
    or umount /overlay && jffs2reset && reboot now (hard factory reset)
  • login via ssh ( root@192.168.27.1) on LAN port (2-5) or 3.3v serial terminal header near the sim card slot
  • disable ixagent completely:
    /etc/init.d/ixagent stop
    /etc/init.d/ixagent disable
  • edit /etc/opkg/distfeeds.conf
    disable or remove src/gz chaos_calmer_ixpackages http://...
    add: src/gz chaos_calmer_luci http://archive.openwrt.org/chaos_calmer/15.05.1/ramips/mt7621/packages/luci
  • insert wan cable (check IP lease) and run the following:
    opkg update
    opkg install luci-ssl Note that uqmi doesn't want to install command line, use luci system software to install
    unsure/future: opkg install luci-app-openvpn
  • via luci (https://192.168.27.1), remove all network firewall zones and add:
    WAN (wan, wan6, wwan) masquerading & MSS clamping (maybe include sta_wan and sta_wan6)
    LAN (lan) allow forward to DESTINATION zones WAN
  • save & apply

enable the 4G router

Note that when a sim card is present, it will connect automatically and be the primary route to internet.

  • go to network interfaces and edit WWAN
    Protocol: DHCP client, switch protocol and set a nice hostname. Save & Apply
  • click Connect
  • if this doesn't seem to work (no RX data), either reboot, go to System Software and install (filter for) uqmi
    login with SSH and type the following:
    /sbin/uqmi -d /dev/cdc-wdm0 --set-device-operating-mode offline
    /sbin/uqmi -d /dev/cdc-wdm0 --set-device-operating-mode reset
    wait 20 seconds
    /sbin/uqmi -d /dev/cdc-wdm0 --set-device-operating-mode online
    /sbin/uqmi -d /dev/cdc-wdm0 --set-autoconnect enabled

enable wifi AP

By default (and using the cloud config generator), the U-blox wifi device is set to station (client) when booting. The script is at /lib/wifi/ublox.sh and it read properties generated via ixrouterconf2uci (not sure whether it's possible to trigger the correct data via the ixconfig). The driver is Marvell WiFi-Ex Driver (cfg80211)

To prepare for accesspoint mode, run the following:

uci set wireless.ap_lan_dev.channel='11'
uci set wireless.ap_lan_iface.ssid='ACKspaceWifi'
uci set wireless.ap_lan_iface.key='Nope. Nope nope nope nope nope.'

To switch, do this:

uci set wireless.ap_lan_dev.disabled='0'
uci set wireless.sta_wan_dev.disabled='1'

To apply the new wifi settings, run /etc/init.d/network reload and to permanently store them, use uci commit

spacenet

Not possible with the current (closed) driver+firmware


Short version: remove wpad-mini and install wpad. Rest might be command line settings only since the web interface for wifi doesn't play nice with the current setup.

setup openVPN (automatically connects)

Note that this will have OpenVPN connect automatically and DNS might give problems. If so, select both WAN and VPN in the second-to-last step.

To connect to the ACKspace VPN (tun), change the interface:

  • go to Network Interfaces and Edit VPN
  • under Physical Settings choose Custom interface: tun+
  • Save & Apply
  • go to Network Firewall and add a Zone:
    VPN (vpn) masquerading (possibly also MSS clamping)
  • Save & Apply
  • locate your ackspace.ovpn file and make sure it contains the following line:
    auth-user-pass /etc/openvpn/login.conf
  • copy the file:
    scp ackspace.ovpn root@192.168.27.1:/etc/openvpn/ackspace.conf
  • SSH into the router and create the following file containing username and password on a separate line: /etc/openvpn/login.conf
  • /etc/init.d/openvpn restart
  • finally, in Luci, go to Network Firewall -> Zone LAN and click Edit
  • switch Allow forward to destination from WAN to VPN
  • Save & Apply

custom scripts

These modified scripts restore some of the functionality that seems to be absent when not using the ixagent daemon.

custom wifi monitor. When 4G/LTE is enabled, the signal quality will display the cell strength (Reference signal received quality).

  • blinking red: pending sim card not active
  • red: bad signal
  • purple: medium signal
  • blue: good signal

Also, the blue act led will light when the VPN is active (and blink when (dis)connecting) /etc/init.d/wifi-monitor

Click here to view the source code
#!/bin/sh /etc/rc.common

START=85
STOP=86
SERVICE_WRITE_PID=1
SERVICE_DAEMONIZE=1
EXTRA_COMMANDS="run_monitor"
EXTRA_HELP=$(cat <<EOF
        run_monitor     Run the signal strength monitor
EOF
)

MONITOR_APP="/bin/sh /etc/rc.common /etc/init.d/wifi-monitor run_monitor"

LED_PATH="/sys/class/leds/ix2:%name:3g"
LED_NAME_RED=red
LED_NAME_BLUE=blue

UPDATE_DELAY=5

LED_MORSE_DELAY=300

log()
{
	echo "wifi-monitor: $1" > /dev/kmsg
}

get_signal_value()
{
	local value=`iwinfo mlan0 info | grep 'Quality'`

	if [[ "$value" == "${value/Link Quality//}" ]]; then
		# No value found
		echo "?"
		return
	fi

	echo "$value" | sed "s/.*Link Quality: //"
}

set_led_status()
{
	local led_name=$1
	local trigger=$2
	local arg=$3

	echo $trigger > ${LED_PATH/%name/$led_name}/trigger

	case $trigger in
	"none")
		echo $arg > ${LED_PATH/%name/$led_name}/brightness
		;;
	"morse")
		echo $arg > ${LED_PATH/%name/$led_name}/message
		echo $LED_MORSE_DELAY > ${LED_PATH/%name/$led_name}/delay
		;;
	"timer")
		echo $arg > ${LED_PATH/%name/$led_name}/delay_on
		echo $arg > ${LED_PATH/%name/$led_name}/delay_off
		;;
	esac
}

update_led()
{
	local signal=$(get_signal_value)
	VPN=$(route|grep tun|awk '{ print $2 }'|grep -v "*"|head -1)
	if [[ -n "$VPN" ]]; then
		ping -W 1 -c 1 $VPN > /dev/null
		VPN=$?
	fi
	if [[ -n "$VPN" ]]; then
		echo "none" > /sys/class/leds/ix2:blue:vpn/trigger
		echo 1 > /sys/class/leds/ix2:blue:vpn/brightness
	elif [[ -n "$(ps w|grep openvpn|grep -v grep)" ]]; then
		echo "timer" > /sys/class/leds/ix2:blue:vpn/trigger
		echo 500 > /sys/class/leds/ix2:blue:vpn/delay_on
		echo 500 > /sys/class/leds/ix2:blue:vpn/delay_off
	else
		echo "none" > /sys/class/leds/ix2:blue:vpn/trigger
		echo 0 > /sys/class/leds/ix2:blue:vpn/brightness
	fi

	# Check if cellular device is enabled multiwan, then dont override
	if [[ "1" == $(uci get mwan3.wwan.enabled) ]]; then
		signal="off"
	# Check if wireless device is enabled
	elif [[ "1" == $(uci get wireless.sta_wan_dev.disabled) ]]; then
		if [[ -x "/sbin/uqmi" ]]; then
			# get rsrq (bad -40 to -3 good) status
			RSRQ=$(/sbin/uqmi -d /dev/cdc-wdm0 --get-signal-info|grep rsrq|grep -Eo "\-[0-9]+")
			if [[ "$RSRQ" -ge -10 ]]; then
				# Excellent
				signal="5/5"
			elif [[ "$RSRQ" -ge -15 ]]; then
				# Ok
				signal="3/5"
			elif [[ "$RSRQ" -ge -20 ]]; then
				# Terrible
				signal="1/5"
			elif [[ "$RSRQ" -ge -40 ]]; then
				# None
				signal="0/5"
			else
				signal="pending"
			fi
		else
			signal="off"
		fi
	elif ! ifstatus sta_wan 2> /dev/null | grep -q "pending.*false"; then
		signal="pending"
		logger -t wifi "Interface 'mlan0' is pending"
	fi

	# Only update signal value when needed
	if [[ "$signal" == "$last_signal" ]]; then
		return
	fi

	case $signal in
            "pending")
		set_led_status $LED_NAME_RED  none 0
		set_led_status $LED_NAME_BLUE timer 1500
                ;;
            "0/5")
		set_led_status $LED_NAME_RED  timer 1500
		set_led_status $LED_NAME_BLUE none 0
                ;;
            "1/5")
		set_led_status $LED_NAME_RED  none 1
		set_led_status $LED_NAME_BLUE none 0
                ;;
            "2/5")
		set_led_status $LED_NAME_RED  none 1
		set_led_status $LED_NAME_BLUE none 1
                ;;
            "3/5")
		set_led_status $LED_NAME_RED  none 1
		set_led_status $LED_NAME_BLUE none 1
                ;;
            "4/5")
		set_led_status $LED_NAME_RED  none 0
		set_led_status $LED_NAME_BLUE none 1
                ;;
            "5/5")
		set_led_status $LED_NAME_RED  none 0
		set_led_status $LED_NAME_BLUE none 1
                ;;
            *)
		set_led_status $LED_NAME_RED  none 0
		set_led_status $LED_NAME_BLUE none 0
                ;;
        esac

	last_signal=$signal
}

start()
{
	service_start $MONITOR_APP
}

stop()
{
	log "Killing wifi signal strength monitor"

	SERVICE_SIG="KILL" service_stop $MONITOR_APP

	set_led_status $LED_NAME_RED none 0
	set_led_status $LED_NAME_BLUE none 0
}

run_monitor()
{
	log "Running wifi signal strength monitor"
	last_signal="off"

	while /bin/true; do
		sleep $UPDATE_DELAY

		update_led
	done
}


custom reset that toggles VPN service if pressed <3s In the future, the opticoupler input will be used for this and the short reset will (re-)enable the access point.

/etc/rc.button/reset

Click here to view the source code
#!/bin/sh /etc/rc.common

APP="leds"

PID_FILE="/tmp/run/rc.button.reset.pid"
LED_PATH_R="/sys/class/leds/ix2:red:status"
LED_PATH_B="/sys/class/leds/ix2:blue:vpn"

log()
{
	echo "rc.button.reset $1" > /dev/kmsg
}

process_reset_button()
{
	# Start sleeping
	sleep 3 &

	local SLEEP_PID=$!

	# Put PID of sleep process to file
	echo $SLEEP_PID > $PID_FILE

	# Wait for sleep to finish
	wait $SLEEP_PID

	# If sleep was killed, do nothing
	if [ "$?" != "0" ]; then
		# Remove PID file so next push can work properly
		log "User let go before timeout - not resetting"
		rm "$PID_FILE"
		exit
	fi

	# User waited 3 seconds after pressing the button. Factory reset time

	# Update file so next button press knows it can't be stopped
	echo "TOOLATE" > $PID_FILE
	log "Waited long enough - factory resetting now"

	# Stop IXagent to get control of LEDs
	log "Stopping IXagent"
	/etc/init.d/ixagent stop

	# Inform user we've started to factory reset
	log "Setting LEDs"
	echo "timer" > $LED_PATH_R/trigger
	echo 50 > $LED_PATH_R/delay_on
	echo 50 > $LED_PATH_R/delay_off

	echo "timer" > $LED_PATH_B/trigger
	echo 60 > $LED_PATH_B/delay_on
	echo 60 > $LED_PATH_B/delay_off

	# Do a reset on the 3G module
	# Should improve stability and ease-of-use
	echo 0 > /sys/class/gpio/3g-perst/value

	# Do the actual factory reset
	jffs2reset -y
	if [ "$?" != "0" ]; then
		log "jffs2reset failed!"
	fi

	reboot
}

if [ "${ACTION}" = "pressed" ]; then
	if [[ -z "$(ps w|grep openvpn|grep -v grep)" ]]; then
		/etc/init.d/openvpn start
	else
		/etc/init.d/openvpn stop
    fi
	if [ -f "$PID_FILE" ]; then
		log "Ignoring pressed - already running"
		exit
	fi

	log "Starting reset"
	process_reset_button &
fi

if [ "${ACTION}" = "released" ]; then
	if [ ! -f "$PID_FILE" ]; then
		log "Ignoring released - not running"
		exit
	fi

	SLEEP_PID=$(cat $PID_FILE)

	if [ "TOOLATE" = "$SLEEP_PID" ]; then
		log "Button released after reset started"
		exit
	fi

	log "Stopping reset"
	kill $(cat $PID_FILE)
	if [ "$?" != "0" ]; then
		log "Kill failed"
		exit
	fi

	log "Reset stopped"
fi

return 0

oneliners

echo 0 > /sys/class/gpio/wifi-pd/value # disable wifi
echo 1 > /sys/class/gpio/wifi-pd/value && wifi reload # enable wifi
echo 0 > /sys/class/gpio/3g-perst/value # disable 3g (fast)
echo 0 > /sys/class/gpio/3g-power-enable/value # disable 3g (slow)

alternative power

It is possible to power the router with a USB-C powerbank for off-the-grid usage, ideal for a hackers on a bike tour. All you need is:

Tested on a fully charged Xiaomi Mi Powerbank 3 (20Ah) and had an uptime of 26:45h

TODO

  • new firmware: determine DSA wan/lan layout location (U-boot?)
  • new firmware: determine gpio pinout mapping
  • new firmware: get/compile working U-blox LILY-W131 (Marvell Avastor 88w8801) driver+firmware
  • new firmware: get/compile working Quectel EC25-E driver
  • determine DNS requests when vpn is active (currently doesn't work)
  • toggle/enable AP upon short reset
  • determine external gpio

also see