简体中文 / [English]


Flashing Armbian on N1 Box and Configuring it as a Soft Router & AP – A Setup Guide

 

This article is currently an experimental machine translation and may contain errors. If anything is unclear, please refer to the original Chinese version. I am continuously working to improve the translation.

Behind every burst bubble, there’s a batch of crying韭菜 (lettuces), and even more joyous garbage hunters having the time of their lives~ (just kidding)

The N1 box has become a thing of the past. But since my Orange Pi is still unrepairable, and Raspberry Pi prices are skyrocketing, the ARM64-powered N1 suddenly looks like a solid alternative. (Well, it just lacks GPIO pins.)

(I really should’ve gone with the N1 instead of the Orange Pi back then, but youth is full of regrets… so now I’m making up for it.)

Sure, the S905 chip can’t compete with the newer S905X3 found in modern foreign-branded set-top boxes, but the N1’s price and popularity have both dropped significantly. The price difference is often more than 2x, sometimes approaching 3x. So I picked up a brand-new, unscratched N1 (K-code intact) from Xianyu (a Chinese secondhand marketplace) for just 90 RMB.

Apart from USB 2.0, it’s practically a perfect little toy.

This time, I’m trying a new approach. With 2GB of RAM—quite generous—I decided to flash Armbian and run OpenWrt inside Docker. It’ll serve as both a server and a soft router. This way, I get access to the latest Linux kernel while running a clean OpenWrt instance—perfect for use as a dorm room router (since 5G Wi-Fi coverage is weak and speed isn’t great).

Since many existing guides for the N1 are outdated or inaccurate, I’ve compiled and verified everything from scratch. Note: This is a post-event write-up, so I missed capturing some steps with screenshots—my apologies.

0x00 Downgrade the Original Firmware

Connect the Phicomm N1 to a display via HDMI. (I personally used a USB capture card—it’s more convenient.)

Also connect a mouse. Power on the device and use the mouse to connect to Wi-Fi.

Then tap the “Firmware Version” four times in a row to reveal the Enable ADB option.

In your command prompt, run adb connect x.x.x.x, where x.x.x.x is the N1’s IP address.

Then run **adb shell reboot fastboot**—the box should reboot into fastboot mode.

Use a dual-headed USB cable to connect your PC’s USB port to the USB port on the N1 closest to the HDMI port.

Similar to iPlay30, you can install the fastboot driver automatically via Windows Update.

Now, flash the older boot, bootloader, and recovery images that support USB booting:

1
2
3
fastboot flash bootloader N1bootloader.img
fastboot flash boot N1boot.img
fastboot flash recovery N1recovery.img

Download the three required files here.

After flashing, run fastboot reboot. The device should boot back into Android (the version number may not change—that’s normal, but the bootloader has been downgraded).

0x01 Prepare the Linux Boot Drive

You can download the latest image compiled by @150balbes: https://disk.yandex.com/d/srrtn6kpnsKz2/RK_AML_AW.

I chose the Debian headless (no GUI) version. No need to extract—just use balenaEtcher to write the image directly to a USB drive.

Since this image supports multiple devices, some boot files need modification to boot correctly.

After writing, Windows should automatically detect the boot partition.

Open the extlinux.conf file inside the extlinux folder, comment out the FDT and APPEND lines under rk-3399, then uncomment the APPEND line under aml s9xxx, and add FDT /dtb/amlogic/meson-gxl-s905d-phicomm-n1.dtb at the end.

If you’re unsure, just replace the entire extlinux.conf content with the following (this ensures the correct dtb is used):

1
2
3
4
5
6
LABEL Armbian
LINUX /zImage
INITRD /uInitrd

FDT /dtb/amlogic/meson-gxl-s905d-phicomm-n1.dtb
APPEND root=LABEL=ROOTFS rootflags=data=writeback rw console=ttyAML0,115200n8 console=tty0 no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0

Rename the u-boot-s905x-s912 file in the boot partition to u-boot.ext. (The N1 uses the S905D SoC, so the S905X u-boot is compatible.)

Add a new file create-mbr-linux.sh to the boot partition with the following content (a script to create an MBR partition table):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/sh
echo "Start script create MBR and filesystem"
DEV_EMMC=/dev/mmcblk1
echo "Start backup u-boot default"
dd if="${DEV_EMMC}" of=/boot/u-boot-default.img bs=1M count=4
echo "Start create MBR and partittion"
parted -s "${DEV_EMMC}" mklabel msdos
parted -s "${DEV_EMMC}" mkpart primary fat32 700M 828M
parted -s "${DEV_EMMC}" mkpart primary ext4 829M 100%
echo "Start restore u-boot"
dd if=/boot/u-boot-default.img of="${DEV_EMMC}" conv=fsync bs=1 count=442
dd if=/boot/u-boot-default.img of="${DEV_EMMC}" conv=fsync bs=512 skip=1 seek=1
sync
echo "Done"
exit 0

Boot drive preparation is now complete.

0x02 Boot into Linux and Flash to eMMC

Back in Android, run adb connect x.x.x.x && adb reboot update to reboot into update mode.

Quickly insert the USB drive into the USB port next to HDMI right after running the command—the system should boot from the USB drive. Do NOT insert the USB drive before or during Android boot, or ext4 permissions may get corrupted.

If it boots into recovery mode instead, that means the USB wasn’t detected. Power off and repeat the ADB command to re-enter the boot process.

After Linux boots, complete initial setup and log in as root.

Run the two scripts: /boot/create-mbr-linux.sh and install-aml.sh.

Wait a moment. If no errors occur, power off, remove the USB drive, and reboot—the system should now boot from eMMC.

p.s.: The N1’s default boot method is unusual—it lacks an MBR partition table, which may cause the install script to fail. That’s why we first run create-mbr-linux.sh to create the partition table before installing.

0x03 Fix the High Average Load Bug in Linux

Reverse-compile the dtb file:
dtc -I dtb -O dts -o n1.dts /boot/dtb/amlogic/meson-gxl-s905d-phicomm-n1.dtb

Edit the n1.dts file using vim.

Comment out the phandle = < 0x21 >; line inside interrupt-controller@9880:

1
2
3
4
5
6
7
8
9
10
interrupt-controller@9880 {
compatible = "amlogic,meson-gpio-intc\0amlogic,meson-gxl-gpio-intc";
reg = < 0x00 0x9880 0x00 0x10 >;
interrupt-controller;
#interrupt-cells = < 0x02 >;
amlogic,channel-interrupts = < 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 >;
status = "okay";
<!-- Comment out the line below -->
#phandle = < 0x21 >;
};

Then recompile and replace the original dtb:

1
2
3
4
dtc -I dts -O dtb -o n1.dtb n1.dts
sudo cp /boot/dtb/amlogic/meson-gxl-s905d-phicomm-n1.dtb /boot/dtb/amlogic/meson-gxl-s905d-phicomm-n1.dtb.bak
sudo cp n1.dtb /boot/dtb/amlogic/meson-gxl-s905d-phicomm-n1.dtb
sudo reboot

After reboot, the high load average issue should be resolved.

0x04 Install Docker and Change Package Sources

Skipped—there are already good guides on Enshan Forum: https://www.right.com.cn/forum/forum.php?mod=viewthread&tid=430903.

0x05 Set Up Wireless Hotspot

Run sudo armbian-config, go to Network → Hotspot. Wait for the required packages to install, then exit.

Edit /etc/default/hostapd and uncomment: DAEMON_CONF="/etc/hostapd.conf".

Run sudo systemctl enable hostapd to ensure hostapd starts on boot.

Replace the content of /etc/hostapd.conf with the following (default is 5G band; change hw_mode and channel for 2.4G):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Wi-Fi name
ssid=Armbian_N1
interface=wlan0
# a for 5G Wi-Fi, g for 2.4G Wi-Fi
hw_mode=a
channel=44
driver=nl80211

logger_syslog=0
logger_syslog_level=0
wmm_enabled=1
wpa=2
preamble=1

# Wi-Fi password
wpa_passphrase=n1wifipassword
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
auth_algs=1
macaddr_acl=0
country_code=CN

## IEEE 802.11n (Don't comment this out even if not using 2.4G!)
ieee80211n=1
ht_capab=[HT40+][SHORT-GI-20][SHORT-GI-40][DSSS_CCK-40]
#ieee80211d=1
## IEEE 802.11n

### IEEE 802.11ac
ieee80211ac=1
vht_capab=[MAX-MPDU-3895][SHORT-GI-80][SU-BEAMFORMEE]
vht_oper_chwidth=1
vht_oper_centr_freq_seg0_idx=42
### IEEE 802.11ac

# Control interface
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0

Then edit /etc/network/interfaces and set iface wlan0 inet manual.

Run sudo systemctl disable NetworkManager to disable Debian’s built-in network manager.

sudo reboot. After reboot, your phone should detect the Wi-Fi. It may hang at “Obtaining IP address,” but you can connect using a static IP—this means the hotspot is working.

(p.s. If hotspot fails, try sudo hostapd -d /etc/hostapd.conf to debug manually. You can also check ps -ef | grep hostapd to see if hostapd is running.)

(p.s.s. I discovered a weird issue: without ht_capab=[HT40+] in the IEEE 802.11n section, 5G 80MHz Wi-Fi fails to start with error Could not set channel for kernel driver. The exact cause is unclear from hostapd docs. But with current settings, 5G 80MHz Wi-Fi (433 Mbps) works fine.)

0x06 Running OpenWRT via Docker

Run sudo docker import https://downloads.openwrt.org/releases/21.02.0/targets/armvirt/64/openwrt-21.02.0-armvirt-64-default-rootfs.tar.gz openwrt:21.02.0 to import the official OpenWRT Docker image.

Enable promiscuous mode on eth0: sudo ip link set eth0 promisc on (allows multiple MAC addresses on one interface).

Now configure networking between OpenWRT and the host.

First, an excerpt from Docker Docs about macvlan:

Some applications, especially legacy applications or applications which monitor network traffic, expect to be directly connected to the physical network. In this type of situation, you can use the macvlan network driver to assign a MAC address to each container’s virtual network interface, making it appear to be a physical network interface directly connected to the physical network. In this case, you need to designate a physical interface on your Docker host to use for the macvlan, as well as the subnet and gateway of the macvlan. You can even isolate your macvlan networks using different physical network interfaces.

And from Docker Docs about bridge:

In terms of Docker, a bridge network uses a software bridge which allows containers connected to the same bridge network to communicate, while providing isolation from containers which are not connected to that bridge network. The Docker bridge driver automatically installs rules in the host machine so that containers on different bridge networks cannot communicate directly with each other.

My approach: pass the host’s eth0 to OpenWRT via macvlan, using eth0 as WAN (get IP via DHCP). Then create a bridge LAN to connect OpenWRT’s LAN with Armbian’s LAN.

  1. Create bridge-lan interface:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    vim /etc/network/interfaces.d/bridge

    # Add the following content. OpenWRT IP: 10.10.10.1, Armbian IP: 10.10.10.2
    auto br-lan
    iface br-lan inet static
    address 10.10.10.2
    netmask 255.255.255.0
    dns-nameserver 10.10.10.1
    gateway 10.168.10.1
    bridge_ports wlan0
  2. In hostapd config, uncomment bridge=br-lan

  3. Create Docker networks:

1
2
3
4
5
6
7
8
9
10
11
12
# Create LAN network lanet
docker network create -d bridge --subnet 10.10.10.0/24 --gateway=10.10.10.1 -o "com.docker.network.bridge.name=br-lan" lanet

# Create WAN network wanet
docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 -o parent=eth0 wanet

# Start container
docker run -d --name op --privileged openwrt:21.02.0 /sbin/init

# Connect networks
docker network connect wanet op
docker network connect lanet op

0x06 Direct NAT and DHCP Setup on Armbian for Router Functionality

Originally, I wanted the box to act like a regular router: connect via Ethernet, obtain IP via DHCP or PPPoE, then assign internal IPs to connected devices.

However, I found Docker’s macvlan setup problematic—it requires specifying the upstream router’s subnet and gateway upfront. (I suspect Docker needs this to configure firewall and routing rules, and since it can’t dynamically get DHCP info, this becomes a hard requirement. This is just my theory—might not be accurate.) Either way, it defeats the purpose of automatic DHCP detection.

So I switched plans: skip OpenWRT and implement all routing features directly on Armbian.

  1. Install dnsmasq (DHCP server) and enable at boot:

    sudo apt-get install dnsmasq

    sudo systemctl enable dnsmasq

  2. Configure wlan0 interface:

    1
    2
    3
    4
    5
    6
    7
    sudo vim /etc/network/interfaces  # Edit network interfaces

    # Change wlan0 settings to:
    allow-hotplug wlan0
    iface wlan0 inet static
    address 10.0.0.1
    netmask 255.255.255.0
  3. Edit dnsmasq config:

    1
    2
    3
    4
    5
    6
    sudo vim /etc/dnsmasq.conf  # Edit config

    # Add:
    interface=wlan0
    dhcp-range=10.0.0.2,10.0.0.100,12h
    dhcp-option=6,10.0.0.1

    This provides DHCP service on wlan0, IP range 10.0.0.2–10.0.0.100, 12h lease, gateway 10.0.0.1.

  4. Enable kernel IP forwarding permanently by adding to /etc/sysctl.conf:

    net.ipv4.ip_forward=1

  5. Set up iptables NAT and forwarding rules—add to startup script:

    1
    2
    3
    4
    5
    6
    7
    sudo vim /etc/rc.local  # Edit startup script

    # Add before exit 0:
    iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    # Only allow established/related connections from eth0 to wlan0
    iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
    iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
  6. Reboot. Connect to the Wi-Fi broadcasted by the N1—you should now have internet access.

0x07 IPv6 Configuration (Bridge Mode)

In universities, IPv6 access is often free and doesn’t require login, so setting it up is worthwhile.

(Though I actually went with the 0x07.1 method below.)

  1. Get IPv6 address on eth0

    Debian should auto-acquire a global IPv6 address. Check with ifconfig. If not, try adding iface eth0 inet6 auto to /etc/network/interfaces.

    However, due to Nanjing University’s weird eduroam network (see this post), Armbian couldn’t get an IPv6 address. My workaround: manually assign one.

    1
    2
    3
    4
    sudo ifconfig eth0 inet6 add 2001:250:5002:8000::2:d666/64
    # Ping multicast router address to discover gateway
    ping6 ff02::2%eth0
    sudo route -A inet6 add default gw fe80::1251:72ff:fe1b:249f dev eth0
  2. Follow instructions from http://www.dohooe.com/2017/02/26/455.html to complete setup.

0x07.1 IPv6 Proxy for Free Internet Access

While IPv6 allows free access on campus, many websites still don’t support it.

So I opted to proxy IPv4 traffic over IPv6. Benefits:

  1. Access home network resources directly from campus via the proxy.
  2. Free access to all IPv4 and IPv6 websites.

Initially considered SSH tunneling, but performance was poor, connections unstable, and it doesn’t support transparent proxying (e.g., RDP can’t go through SOCKS5).

Switched to the popular tool: v2Ray.

  1. Set up a server with both IPv4 and IPv6. (If you don’t have one, consider the IPv6 bridging method above.)

    Run the proxy server. Sample config below. Note: listen: "[::]" means listening on IPv6.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    {
    "inbounds": [{
    "port": 9000,
    "listen": "[::]",
    "protocol": "vmess",
    "settings": {
    "clients": [
    {
    "id": "c95f3ab6-62c2-4426-8027-7833c7ba2e86",
    "level": 1,
    "alterId": 0
    }
    ]
    }
    }],
    "outbounds": [{
    "protocol": "freedom",
    "settings": {}
    }]
    }

    Setup details omitted.

  2. Install v2Ray client on Armbian: sudo apt install v2ray

    Client config (for reference):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    {
    "inbounds":[
    // This inbound is for my phone/tablet to connect via LAN (relay). Remove if not needed.
    {
    "port": 8503,
    "listen": "172.26.73.226",
    "protocol": "vmess",
    "settings": {
    "clients": [{
    "id": "c95f3ab6-62c2-4426-8027-7833c7ba2e86",
    "level": 1,
    "alterId": 0
    }]
    }
    },
    {
    "port":12315,
    "protocol":"dokodemo-door",
    "settings":{
    "network":"tcp,udp",
    "followRedirect":true
    },
    "sniffing":{
    "enabled":true,
    "destOverride":[
    "http",
    "tls"
    ]
    }
    }
    ],
    "outbounds":[
    // First outbound is default proxy
    {
    "tag":"proxy",
    "protocol":"vmess",
    "settings":{
    "vnext":[
    {
    // Replace these with your server settings!
    "address":"ipv6.xxxxx.com",
    "port":9000,
    "users":[
    {
    "id":"c95f3ab6-62c2-4426-8027-7833c7ba2e86",
    "alterId":0
    }
    ]
    }
    ]
    }
    },
    {
    "protocol": "freedom",
    "settings": {},
    "tag": "direct"
    }
    ],
    "routing":{
    "domainStrategy":"IPOnDemand",
    "rules":[
    // Don't proxy 172.x campus network
    // Don't proxy 10.x Armbian internal network
    // Proxy everything else
    {
    "type":"field",
    "outboundTag":"direct",
    "ip":[
    "10.0.0.0/8",
    "172.0.0.0/8"
    ]
    }
    ]
    }
    }

    After config, run: sudo systemctl enable v2ray && sudo systemctl start v2ray

  3. Configure gateway. Add to /etc/rc.local before exit 0:

    1
    2
    3
    4
    5
    iptables -t nat -N V2RAY
    # Only allow internal network to use transparent proxy
    iptables -t nat -A V2RAY -p tcp -s 10.0.0.0/24 -j REDIRECT --to-ports 12315
    iptables -t nat -A V2RAY -p udp -s 10.0.0.0/24 -j REDIRECT --to-ports 12315
    iptables -t nat -A PREROUTING -p all -j V2RAY
  4. Reboot. Connect to the Wi-Fi from Armbian—no login required, internet should work.

0x08 Mission Accomplished!

Now you can enjoy both a personal playground server and a home-like network environment in your dorm. :P

Appendix 0x00 Bluetooth Driver Issue on Armbian

The default image compiled by @150balbes has Bluetooth disabled. You need to replace the dtb file.

Download the correct dtb: https://www.right.com.cn/forum/forum.php?mod=viewthread&tid=4057309

Bluetooth activation guide: https://www.right.com.cn/forum/thread-517710-1-1.html

Direct download link: https://pan.lyc8503.net/Public/%E5%9B%BA%E4%BB%B6/n1/meson-gxl-s905d-phicomm-n1.dtb

To enable Bluetooth, download and replace /boot/dtb/amlogic/meson-gxl-s905d-phicomm-n1.dtb (remember to back up!).

Tested and confirmed: Bluetooth works perfectly after replacement—Armbian runs flawlessly.

This article is licensed under the CC BY-NC-SA 4.0 license.

Author: lyc8503, Article link: https://blog.lyc8503.net/en/post/phicomm-n1/
If this article was helpful or interesting to you, consider buy me a coffee¬_¬
Feel free to comment in English below o/