Skip to content

51ddns-agent: add package - #30158

Open
21hkcloud wants to merge 2 commits into
openwrt:masterfrom
21hkcloud:codex/51ddns-agent-0.6.1
Open

51ddns-agent: add package#30158
21hkcloud wants to merge 2 commits into
openwrt:masterfrom
21hkcloud:codex/51ddns-agent-0.6.1

Conversation

@21hkcloud

@21hkcloud 21hkcloud commented Aug 6, 2026

Copy link
Copy Markdown

Description

Add the open-source client for the commercial, vendor-hosted 51DDNS remote-access service.

The package:

  • builds Agent v0.6.3 from Apache-2.0 licensed Go source;
  • uses the feed-provided frpc package instead of downloading a bundled binary;
  • runs as the dedicated unprivileged ddns51 user in a procd/ujail sandbox;
  • stores credentials with restricted permissions and preserves them on sysupgrade.

The service trust boundary is documented explicitly: the 51DDNS control plane assigns the FRP relay configuration, so users should install the client only if they trust the service operator.

LuCI and documentation

The LuCI interface is submitted independently, as required:
openwrt/luci#8958

English installation, configuration, privacy, troubleshooting and removal documentation:
https://www.51ddns.com/openwrt

Agent source and privacy notice:
https://github.com/21hkcloud/51ddns-openwrt/tree/v0.6.3

The v0.6.3 source archive does not contain luci-app-51ddns.

Testing

Source builds have been exercised for:

  • x86_64
  • aarch64_cortex-a53
  • mips_24kc
  • mipsel_24kc

Runtime tested on OpenWrt 25.12.5 (x86_64 and aarch64) and OpenWrt 24.10 (ramips/mt7621).

@21hkcloud

21hkcloud commented Aug 6, 2026 via email

Copy link
Copy Markdown
Author

@BKPepe BKPepe left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description says "self-hosted 51DDNS control plane", but the README in your repo states Apache-2.0 only covers the client, and the default control_url points at api.51ddns.com. So in practice this is a client for a closed commercial cloud, nobody can self-host it. Please fix the description.

The bigger question: the agent pulls frpc configs from your API at runtime, meaning whoever operates api.51ddns.com controls what gets tunneled out of the user's network. Upstream is a repo created for this purpose (0 stars, 20 commits, no releases), so there is zero track record. On top of that the README, the website and the console are Chinese-only, so most users of this feed can't even read what the service does or what your privacy policy says before handing you a tunnel into their LAN. English docs are the bare minimum. Personally I'm not convinced the feed should carry a remote-access agent for an unknown commercial service at all.

Code-wise:

  • everything runs as root, no procd user, no ujail. frpc doesn't need root for outbound tunnels, so why does the agent?
  • validate_agent_section() is defined but never called
  • extensions_enabled, webdav_enabled and remote_wakeup_enabled are shipped in the default config but the init script never touches them. Does the binary read UCI directly? WebDAV and remote wakeup also sound like considerably more than "DDNS", the package description should say what this thing actually does.
  • the custom postinst can go, enable happens by default anyway and restarting on install is odd
  • reload_service is just stop/start, so the reload trigger hard-restarts on every config change

PKG_MAINTAINER and Signed-off-by have to be a real person, "51DDNS support@51ddns.com" won't be accepted. And given the codex/ branch name this looks largely AI-generated, which is fine as such, but who is actually going to maintain this?

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 commit (2619ea1); the commit message matches the diff.

None of this blocks a merge outright — the formality checks are green, and the upstream v0.6.1 tag resolves (git ls-remote https://github.com/21hkcloud/51ddns-openwrt v0.6.1cb8c6ba). The two I would fix before merge are the /var/lib/51ddns directory shipped in the package payload (/var is a symlink to /tmp, so it never survives a reboot) and the custom postinst, which re-enables the service on every upgrade because it does not honour the PKG_UPGRADE guard that default_postinst applies. The remaining comments are dead code (validate_agent_section, restart_service, SERVICE_NAME), unused UCI options, and one question about whether multiple agent sections are meant to be supported — all optional.


Generated by Claude Code

Comment thread net/51ddns-agent/Makefile Outdated
Comment thread net/51ddns-agent/Makefile Outdated
Comment thread net/51ddns-agent/Makefile Outdated
Comment thread net/51ddns-agent/files/51ddns-agent.init Outdated
Comment thread net/51ddns-agent/files/51ddns-agent.init Outdated
Comment thread net/51ddns-agent/files/51ddns-agent.init
Comment thread net/51ddns-agent/files/51ddns.config Outdated
@BKPepe BKPepe added the NAK pull request with at least one NAK from maintainers label Aug 6, 2026
@21hkcloud
21hkcloud force-pushed the codex/51ddns-agent-0.6.1 branch 2 times, most recently from 86f64a1 to 61ed44a Compare August 6, 2026 08:00
@21hkcloud
21hkcloud force-pushed the codex/51ddns-agent-0.6.1 branch from 61ed44a to a72f415 Compare August 6, 2026 08:02
@21hkcloud
21hkcloud force-pushed the codex/51ddns-agent-0.6.1 branch from a72f415 to 34c066d Compare August 6, 2026 08:18
@21hkcloud
21hkcloud force-pushed the codex/51ddns-agent-0.6.1 branch from 34c066d to 1dd7972 Compare August 6, 2026 08:20
@21hkcloud

Copy link
Copy Markdown
Author

Thank you for the detailed review. I agree that the original wording and trust boundary were inaccurate.

I have force-pushed commit 1dd7972. The update:

  • describes 51DDNS explicitly as a commercial, vendor-hosted service at api.51ddns.com and documents that the service operator supplies the runtime FRP configurations;
  • adds an English README/trust model and an English privacy notice;
  • changes PKG_MAINTAINER to Jinshuan Wang 21hkcloud@gmail.com;
  • runs the Agent and its frpc children as the dedicated unprivileged ddns51 user with no_new_privs inside procd/ujail;
  • removes /var/lib/51ddns from the package payload and creates runtime state during service startup;
  • removes the custom postinst, redundant reload/restart code, unused UCI options, and multiple-section ambiguity; validation now applies to the single main section;
  • uses a valid OpenWrt service account name after the SDK correctly rejected the earlier digit-prefixed name.

Validation is now green:

  • all three OpenWrt FormalityCheck jobs pass;
  • the full 8-job OpenWrt/ImmortalWrt source-build matrix passes for x86_64, aarch64_cortex-a53, mips_24kc, and mipsel_24kc: build run 31084340243;
  • runtime install/upgrade, configuration preservation, restart, reboot, control-plane reconnect, and FRP login were tested on OpenWrt 25.12.5, ramips/mt7621.

Documentation and source:

The Agent is maintained by me, Jinshuan Wang, with company support from Shake Cloud Inc.

I understand the policy concern about a vendor-hosted remote-access service. If this category is out of scope for the feed regardless of hardening and disclosure, I will respect that and keep distribution in third-party feeds. Otherwise, I would appreciate another review of the corrected package.

@21hkcloud
21hkcloud requested a review from BKPepe August 6, 2026 08:55

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at 1dd7972 (force-push over 2619ea1). All seven findings from the previous round are addressed: /var/lib/51ddns is out of the payload, the custom postinst is gone, validate_agent_section/restart_service/SERVICE_NAME and the three unused UCI options are removed, the multi-section ambiguity is resolved into a single main section, and the description no longer claims "self-hosted". The upstream v0.6.2 tag resolves (git ls-remote3b8ae05) and the three FormalityCheck jobs are green.

The one I would fix before merge is the jail mount list: the agent execs /usr/bin/frpc, which is not mounted, so on an image with procd-ujail the tunnel cannot start. That also raises a question about the runtime test — procd-ujail is not in DEPENDS and procd_add_jail is used without requirejail, so a successful FRP login on the test device is consistent with the jail never having been applied. Worth confirming before the hardening claim in the commit message is taken at face value.

Secondary: the reload trigger was removed along with reload_service, so UCI changes no longer apply without a manual restart; uci_validate_section's return code is discarded; and the generated device identity under /etc/51ddns does not survive sysupgrade.

None of this speaks to @BKPepe's policy question about whether the feed should carry a vendor-hosted remote-access agent at all — that call is the maintainers'.


Generated by Claude Code

Comment thread net/51ddns-agent/files/51ddns-agent.init
Comment thread net/51ddns-agent/files/51ddns-agent.init
Comment thread net/51ddns-agent/files/51ddns-agent.init Outdated
Comment thread net/51ddns-agent/files/51ddns-agent.init
Comment thread net/51ddns-agent/Makefile
@21hkcloud
21hkcloud force-pushed the codex/51ddns-agent-0.6.1 branch 2 times, most recently from f70640f to 2ecae04 Compare August 6, 2026 11:19
@21hkcloud

Copy link
Copy Markdown
Author

Thanks for the re-review. Addressed in 2ecae04:

  • require procd-ujail, add requirejail, and explicitly mount /usr/bin/51ddns-agent, /usr/bin/frpc, /bin/sleep, and /usr/bin/logger in the jail;
  • restore procd_add_reload_trigger 51ddns without a custom reload_service, so procd can diff and reload the instance;
  • abort startup when uci_validate_section fails;
  • preserve /etc/51ddns/ across sysupgrade via /lib/upgrade/keep.d/51ddns-agent.

I also re-ran the jail path on OpenWrt 25.12.5 ramips/mt7621. service info reported the 51ddns-agent jail and the explicit mounts, ps showed the agent launched by /sbin/ujail, and the child frpc logged in successfully. The original test service was restored afterward.

All three FormalityCheck jobs pass. The OpenWrt/ImmortalWrt source-build matrix now passes all 8 targets (mipsel_24kc, mips_24kc, aarch64_cortex-a53, and x86_64 on both): https://github.com/21hkcloud/51ddns-openwrt/actions/runs/31096771374

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at 2ecae04 (force-push over 1dd7972). The commit message still matches the diff.

Correction to my previous round: the /bin/sh point I raised on the wrapper was wrong, and I should say so plainly. ujail runs add_path_and_deps() on the jail command and on every procd_add_jail_mount path, and that function detects a #! header and mounts the interpreter itself (add_script_interp() in jail/fs.c:464-485, reached from fs.c:544-546). /usr/libexec/51ddns-agent-start therefore pulls /bin/sh in on its own — which is why core inits jail #!/bin/sh scripts without mounting it. Same mechanism means /etc/passwd and /etc/group are added by ujail automatically once user/group is set (jail.c:2961-2963).

The mounts you did add are the ones that were genuinely missing: /usr/bin/51ddns-agent and /usr/bin/frpc are exec'd at runtime rather than being shebang/ELF deps ujail can discover, and /bin/sleep / /usr/bin/logger are busybox children of the wrapper. Bind-mounting those symlinks resolves through to /bin/busybox and busybox dispatches on argv[0], so they work as written. With log on the jail giving /dev/log, the mount list looks complete to me now.

The rest of last round is addressed as well: uci_validate_section failure now aborts startup, and service_triggers/procd_add_reload_trigger 51ddns is back — with no reload_service defined, rc.common's reload() falls through to start and lets procd diff the instance (rc.common:165-172). The keep.d drop-in follows the same install shape as openvpn/gnunet/privoxy, and /etc/51ddns/ as a directory entry is fine — list_static_conffiles feeds those lines straight to find (sysupgrade:167-171).

One new finding, inline: the +procd-ujail dependency takes the package off every small_flash target. Nothing here blocks a merge on its own.

The config_load 51ddns on line 19 is still dead (validate_data reads UCI itself) — cosmetic, not worth a force-push by itself.

FormalityCheck is green on 2ecae04. As before, none of this touches @BKPepe's policy question about whether the feed should carry a vendor-hosted remote-access agent at all; that remains the maintainers' call.


Generated by Claude Code

Comment thread net/51ddns-agent/Makefile Outdated
Add the open source client for the vendor-hosted 51DDNS remote access
service. The package builds Agent v0.6.2 from the Apache-2.0 source
release and uses the feed-provided frpc package at runtime.

The procd service runs as the dedicated unprivileged ddns51 user and
enters an ujail where the target provides it. English trust-model and
privacy documentation are available upstream.

Upstream release:
https://github.com/21hkcloud/51ddns-openwrt/tree/v0.6.2

Tested with OpenWrt and ImmortalWrt SDKs on:
- x86_64
- aarch64_cortex-a53
- mips_24kc
- mipsel_24kc

Runtime-tested on OpenWrt 25.12.5, ramips/mt7621.

Signed-off-by: Jinshuan Wang <21hkcloud@gmail.com>
@21hkcloud
21hkcloud force-pushed the codex/51ddns-agent-0.6.1 branch from 2ecae04 to 40f8e2e Compare August 6, 2026 13:09
@21hkcloud
21hkcloud requested a review from openwrt-ai August 6, 2026 13:37

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at 40f8e2e (force-push over 2ecae04). Three lines changed, all of them last round's finding: +procd-ujail is out of DEPENDS, requirejail is off procd_add_jail, and the dead config_load 51ddns is gone.

That resolves the small_flash exclusion. I checked that nothing else re-introduces the transitive KERNEL_NAMESPACES dependency — frpc carries only $(GO_ARCH_DEPENDS) (frp/Makefile:58) and ca-bundle has no config symbols — so the package is selectable on ramips/mt76x8, ath79/tiny and friends again, which is the install base the mips test matrix speaks to. The remaining posture (jail applied wherever /sbin/ujail exists, service unjailed but still unprivileged elsewhere) is what core does: dnsmasq.init:1277 jails without depending on procd-ujail, and sysntpd:73 guards its jail block on the binary being present.

Dropping config_load 51ddns is correct: uci_validate_section goes through /sbin/validate_data, which reads UCI itself, and nothing else in the script uses config_get/config_foreach any more.

The commit message still matches the diff, and was updated for the softened jail claim. No new issues; one wording nit inline about the PR body, which still describes the jail as unconditional.

FormalityCheck reports nothing failing on 40f8e2e. As in previous rounds, none of this addresses @BKPepe's policy question — whether the feed should carry a client for a vendor-hosted remote-access service at all — and the NAK label suggests that is where the PR actually stands. That call is the maintainers'.


Generated by Claude Code

Comment thread net/51ddns-agent/Makefile
@21hkcloud

Copy link
Copy Markdown
Author

Hello, just a polite follow-up on the remaining policy question.

The technical findings have been addressed, the FormalityCheck jobs remain green, and the client, trust model, privacy notice, and vendor-hosted nature of the service are now documented explicitly. I understand and respect that inclusion of a client for a commercial vendor-hosted remote-access service is ultimately a feed policy decision.

When convenient, could a maintainer please confirm whether this package category is considered out of scope for the official feed, or whether the corrected package may proceed to final review? A clear decision either way would help us choose the appropriate long-term distribution channel. Thank you.

@BKPepe

BKPepe commented Aug 20, 2026

Copy link
Copy Markdown
Member

Looking at this again, you currently have two open pull requests: this one and #30176. They are essentially the same thing, and looking at both websites, they appear visually similar and AI-generated. The only difference being that one supports English while the other is entirely in Chinese with no translation options.

At the same time, @openwrt-ai keeps pointing this out:

As before, none of this touches @BKPepe's policy question about whether the feed should carry a vendor-hosted remote-access agent at all

Frankly, I am quite strongly against adding a package when there is no LuCI interface, no documentation, and the website is incomprehensible to me. Furthermore, luci-app-51ddns in your repository belongs in openwrt/luci and should not be bundled inside the tarball being downloaded.

So we essentially have a package, but no way of knowing how to actually use it.

Therefore, my NAK still stands and nothing has changed.

Remove the LuCI application from the agent source archive.

This allows the web interface to be reviewed independently in the openwrt/luci feed.

Signed-off-by: Jinshuan Wang <21hkcloud@gmail.com>
@21hkcloud

Copy link
Copy Markdown
Author

Thank you for the direct feedback. I have now addressed each concrete issue:

The package and documentation now make the vendor-hosted nature and relay trust boundary explicit. I understand that the remaining question is the feed policy decision about carrying this class of client, and I will respect the maintainers' decision. If there are further technical issues in either PR, I will address them there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Add package NAK pull request with at least one NAK from maintainers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants