Synology DSM 给 File Station 绑定到 443 端口

登录门户 > 应用程序 > File Station 设置 网页服务 或者

输入都能看到预览,网页服务别名是把入口放在子目录;域是用子域名。

Synology 共享整个共享文件夹

「安全」的 Synology 限制真多,一是无法共享整个 ” 共享文件夹 “,就是创建在存储空间根的目录;二是共享产生的链接是 gofile.me 域下的,我想要用自己的域名就得倒一手;三是 File Station 不让匿名访问,一定得安排个账号,Guest 都不让用了。

启个文件服务器真难,不想搞 alist 那套复杂系统,用 Web Station Nginx 了。

Web Station 默认还不启用 File Listing,得改用户配置文件,再重载 Nginx

sudo mkdir /usr/local/etc/nginx/conf.d/ae449a70-2ae2-4cdc-9c15-f861a8c9233b
sudo cat > /usr/local/etc/nginx/conf.d/ae449a70-2ae2-4cdc-9c15-f861a8c9233b/user.conf << EOF
autoindex on;
EOF

启动 WSL 报错由于系统缓冲区空间不足或队列已满不能执行套接字上的操作

未解之谜

由于系统缓冲区空间不足或队列已满,不能执行套接字上的操作。  
错误代码: Wsl/Service/0x80072747
 
An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
Error code: Wsl/Service/0x80072747
dmesg
[29586.931479] WSL (102269 - SessionLeader) ERROR: UtilAcceptVsock:271: accept4 failed 110  
[29586.932142] WSL (102269 - SessionLeader) ERROR: operator():1238: UtilAcceptVsock() failed for session leader 110  
[29609.895784] WSL (100159 - Relay) ERROR: UtilAcceptVsock:244: Waiting for abnormally long accept(11)

在存活的终端执行命令来看,表现是从 WSL 中连接不上 Windows 主机。

目前只有重启 WSL 的法子。

MSYS2 的 rsync 上传到 Synology 报错

在执行 rsync 的时候一直失败,提示没权限 Permission denied, please try again

$ rsync -avzh . enihsyou.synology.me:/volume2/pve/helper-scripts/
Permission denied, please try again!
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
      0 [sig] rsync 1895! sigpacket::process: Suppressing signal 30 to win32 process (pid 67512)
rsync error: error in rsync protocol data stream (code 12) at io.c(232) [sender=3.4.1]

命令基础,可执行文件位置不基础

一开始我以为是 Synology 的 SSH 默认给的 PATH=/usr/bin:/bin:/usr/sbin:/sbin 中不包含 rsync,所以按照 linux - How can rsync fail due to missing permissions if remote login occurs with root? - Super User 的介绍,添加 --rsync-path 参数尝试,值是在服务器上执行 which rsync 的结果。给了个不同的错误:

$ rsync -avzh . enihsyou.synology.me:/volume2/pve/helper-scripts/ --rsync-path '/bin/rsync'
sh: C:/msys64/usr/bin/rsync: No such file or directory

MSYS2 路径自动转换 MSYS2 和 OpenSSH

加个 -v 参数看下,发现实际的参数路径有问题,多了个前缀。

$ rsync -avzh . enihsyou.synology.me:/volume2/pve/helper-scripts/ --rsync-path '/bin/rsync' -e 'ssh -v'
debug1: Sending command: C:/msys64/usr/bin/rsync --server -vlogDtprze.iLsfxCIvu . C:/msys64/volume2/pve/helper-scripts/
debug1: pledge: fork
sh: C:/msys64/usr/bin/rsync: No such file or directory

因为 Windows 没有原生的 rsync,我用 MSYS2 安装的,明显这里没做路径转换。一查就是老问题

直接调用 MSYS2 的 rsync 会触发 Automatic Unix ⟶ Windows Path Conversion,把 /bin/rsync 转为 $(cygpath -m /bin/rsync)
在 Windows 中尝试加上 MSYS2_ARG_CONV_EXCL='*' 或者 MSYS_NO_PATHCONV=1,都能得到正确的路径转换结果,但产生了另一个错误 rsync service is no running (code 43) 🫠。

$ $env:MSYS2_ARG_CONV_EXCL='*'
$ rsync -avzh /g/GitHub/ProxmoxVE enihsyou.synology.me:/volume2/pve/helper-scripts/ --rsync-path '/bin/rsync' -e 'ssh -v'
debug1: Sending command: /bin/rsync --server -vlogDtprze.iLsfxCIvu . /volume2/pve/helper-scripts/
debug1: pledge: fork
rsync error: rsync service is no running (code 43) at io.c(254) [Receiver=3.1.2]
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
      0 [sig] rsync 886! sigpacket::process: Suppressing signal 30 to win32 process (pid 52260)
rsync error: error in rsync protocol data stream (code 12) at io.c(232) [sender=3.4.1]

实在是摸不到头脑,最后我选择在 WSL 下运行 rsync,很顺利就成功了 😅

$ rsync -avzh . enihsyou.synology.me:/volume2/pve/helper-scripts/ --rsync-path '/bin/rsync'
sending incremental file list
...
sent 39.81M bytes  received 56.59K bytes  2.95M bytes/sec
total size is 45.81M  speedup is 1.15

2025-09-12 其实需要 MSYS2 版的 OpenSSH 客户端(-e '/usr/bin/ssh'),以及配置好 ssh-agent 认证,这下连路径都不用变了。
因为是从 Windows 环境下直接调用的 rsync,会把当前 Windows 环境的 PATH 继承给 rsync,那么 lookup_path(ssh) 得到的就是 Win32-OpenSSH,而非 OpenSSH from MSYS2。

不过如果是从 Windows 发起的请求,PATH 中排在前面的肯定是 OpenSSH_for_Windows,而不是 MSYS2 SSH,那还是指定完整路径更简单。

$env:MSYS2_ARG_CONV_EXCL='/'
rsync -avzh -CP . pve:public -e "C:\msys64\usr\bin\ssh.exe"
rsync -avzh -CP . pve:public -e '/usr/bin/ssh' --rsync-path '/bin/rsync'

2025-10-09 给出当前的解决方案,需要一些前置设置

socat 转发 Windows SSH Agent
$PSNativeCommandArgumentPassing="Standard"
$env:SSH_AUTH_SOCK="/tmp/run/ssh-agent.sock"
msys2 setsid socat -v "UNIX-LISTEN:/tmp/run/ssh-agent.sock,umask=007,fork" "EXEC:'npiperelay-msys2.exe -ei -s //./pipe/openssh-ssh-agent',nofork"
rsync -avzh -CP ./buildout paimon: -e '/usr/bin/ssh'

添加 shell alias 可以简化 -e 参数 function rsync { rsync.exe -e /usr/bin/ssh @args },在 Synology 中开启 rsync 服务可以省去 --rsync-path 参数

误导人的认证失败报错信息

但仔细看看,这 /bin/rsync 路径确实包含在 PATH=/usr/bin:/bin:/usr/sbin:/sbin 中呀 😦。

进一步的测试显示更奇怪的表现:要执行的命令只要以 rsync 为前缀,都提示 Permission denied

$ ssh enihsyou.synology.me 'rsync' 
Permission denied, please try again.
$ ssh enihsyou.synology.me 'true;rsync'
rsync  version 3.1.2  protocol version 31
 
$ ssh enihsyou.synology.me 'rsync1'
Permission denied, please try again.
$ ssh enihsyou.synology.me 'true;rsync1'
sh: rsync1: command not found

尝试过重命名、移动 rsync、在 rsync 位置放一个其他可执行文件,基本确认是对这个名字名字有黑名单,只要是命令匹配 rsync.* 就会触发这个错误。
这一错误发生在认证完成后、执行 command 的阶段,和密码、密钥无关。

这么离谱的行为,先挂 strace 观测下系统调用:

# 先找到 sshd 的根
pgrep sshd -l
# 然后挂上去输出到文件
sudo strace -p 9283 -v -f -o strace.txt
# 另一个终端里触发 ssh
ssh enihsyou.synology.me rsync
# 再一个终端里执行不一样的内容做对比
ssh enihsyou.synology.me true

发现正常的命令会在读取 /etc/synoinfo.conf 后加载 /etc/passwd,而 rsync 命令加载 /etc/synoinfo.conf 后很快就抛错误信息死了。

从 OpenSSH 源码就找到一个会抛出 Permission denied, please try again. 的位置,还是在认证前,我就不信还能是因为密码错误。

直接 vim -b 修改二进制,把在 TEXT 段落报错信息最后的 . 改成 !,看看是 PAM 组件还是别的什么代码抛的。

一运行还真是 sshd 抛出来的,那思路清晰了。提取字符串一看,在 sshd 中出现了本不应出现的 rsync 关键字,那很明显了,Synology 自带的 sshd 有私货。

$ strings sshd | grep rsync  
rsync_sshd_port  
%s:%d Failed to get rsync_sshd_port of synoinfo.conf. [0x%04X %s:%d]  
rsync

再掏出 IDA 看看逻辑,直接搜索 Permission denied, please try again 就能找到几个使用它的函数,伪代码逻辑大概这样。

  else if (!strncmp(haystack, "rsync", 5 u)) {
    if (!sub_1E258(haystack)) {
      if (v19) {
        username_1 = * v19;
        if ( * v19) {
          if (strchr( * v19, 92)) {
            v20 = 2;
          } else if (strchr(username_1, 64)) {
            v20 = 8;
          } else {
            v20 = 1;
          }
        } else {
          v20 = 0;
        }
 
        if (SYNOServiceUserHomeIsEnabled(v20, v19 + 2) && SLIBServiceHomePathCreate( * v19) < 0)
          _fprintf_chk(stderr, 2, "Could not create home for '%s'\n", * v19);
        username_2 = * v19;
        if (strcmp( * v19, "root")) {
          if (strcmp(username_2, "admin")) {
            shell = (char * ) v19[6];
            if (shell) {
              free(shell);
              v19[6] = (const char * ) sub_67BC4("/bin/sh");
            }
          }
        }
      }
      if (setenv("AUTHDONE", "SUCCESS", 0) == -1)
        goto LABEL_71;
      v109[0].pw_name = 0;
 
      if (!SYNOServiceSSHIsRegister("rsync", v23, v24, 0))
        goto LABEL_71;
 
      if (read_rsync_sshd_port(v109) < 0) {
        v89 = SLIBCErrGet();
        File = (const char * ) SLIBCErrorGetFile();
        Line = SLIBCErrorGetLine();
        _syslog_chk(3, 2, "%s:%d Failed to SYNORsyncSSHPortGet().[0x%04X %s:%d]", "session.c", 1746, v89, File, Line);
        goto LABEL_71;
      }
 
      v25 = (char * ) sub_612BC(a1);
      if (v25 != v109[0].pw_name) {
LABEL_71:
 
        fwrite("Permission denied, please try again!\n", 1 u, 0x25 u, stderr);
        exit(1);
      }
      v102 = 3;
      goto LABEL_70;
    }
    goto LABEL_72;
  }

我怀疑是因为 SYNOServiceSSHIsRegister 验证不通过,跳转到 LABEL_71 的。不论它的逻辑是什么,从名字看应该是检查 Rsync 服务有没有开启。

参照 Rsync | DSM - Synology Knowledge Center ,在 Control Panel > File Services > rsync 确实没有打开 Rsync 服务。点击开启并重试,瞬间成功了 🙂。

最终的部署指令是个 Taskfile

Taskfile.yml
version: '3'
tasks:
  rsync:
    cmds:
    - wsl 
      rsync -avzh -CP --rsync-path '/bin/rsync'
      . enihsyou.synology.me:/volume2/pve/helper-scripts/

我在哪都没找到 Synology DSM 关于通过 SSH 使用 Rsync 需要启用服务的相关说明,即便 Synology 的目的是不想让 Rsync 客户端连接上未开启 Rsync 功能的服务器,以提升安全性,但硬编码在代码中的报错信息也非常有误导性,非常差劲的做法。结合最近用认证限制自由 HDD 这种企图垄断的行为,BAD Synology 😡

Synology /usr/syno/sbin/syno_system_dump 中的语法错误

搜日志时发现在 /var/log/bash_err.log 中有每分钟一次的错误,看着是语法错误?

2025-08-31T03:45:10+08:00 enihsyou-NAS bash[11657]: BASH_ERR: builtin_error [ (11655)"/usr/sbin/CROND -n" -> (11656)"/bin/bash /usr/syno/sbin/syno_system_dump" -> (11657)"/bin/bash /usr/syno/sbin/syno_system_dump" ] /usr/syno/sbin/syno_system_dump:198: [: 12
2: integer expression expected

相关代码是在判断 if [ "$tmp_percentage" -ge 95 ],但实际执行起来是有两个输出

$ df_result=$(df -x fuse.gvfsd-fuse -x cifs -x nfs4 -x nfs)
$ echo "$df_result" | grep "% /tmp" | awk '{print $5}' | sed 's/%//'
12
2

检查下是有两个 /tmp

$ df -x fuse.gvfsd-fuse -x cifs -x nfs4 -x nfs
Filesystem      1K-blocks       Used  Available Use% Mounted on
/dev/md0          2385528    1182676    1084068  53% /
devtmpfs           254548          0     254548   0% /dev
tmpfs              256284         16     256268   1% /dev/shm
tmpfs              256284      31496     224788  13% /run
tmpfs              256284          0     256284   0% /sys/fs/cgroup
tmpfs              256284      30212     226072  12% /tmp
/dev/loop0          27633        383      24957   2% /tmp/SynologyAuthService
/dev/vg1001/lv 3840822576 3509528336  331175456  92% /volume2
/dev/vg1000/lv 2879396352 1733402944 1145874624  61% /volume1

先不去排查原因了,直接卸载

$ mount | grep /tmp/SynologyAuthService
/tmp/SynologyAuthService-block on /tmp/SynologyAuthService type ext4 (rw,relatime,journal_checksum,data=ordered)
 
$ sudo umount /tmp/SynologyAuthService