nextcloud云盘https使用frp穿透访问

Nextcloud是 ownCloud 创始人发起的分支项目,是一款用于自建企业云存储(私有网盘)的开源软件。支持 PC、IOS 和 Android 三个同步客户端,用户可以很方便地与服务器上存储的文件、日程安排、通讯录、书签等重要数据保持同步。它还支持将数据保存到第三方存储中:Amazon S3、Dropbox、FTP、Google Drive、SMB、WebDAV、SFTP等。
frp是一个开源、简洁易用、高性能的内网穿透和反向代理软件,支持 tcp, udp, http, https等协议。frp项目官网是 https://github.com/fatedier/frp.
外网用户通过https使用frp穿透访问内网Nextcloud云盘, 如果配置不好经常会遇到访问https://xxxx.com:port/nextcloud,会跳转到内网地址,或者跳转http://xxxx.com/nextcloud(不带端口http协议),http://xxxx.com:port/nextcloud(带端口http协议)。

1.frpc.ini设置

修改frpc.ini。与配置有个两个关键配置:plugin_host_header_rewrite, plugin_header_X-From-Where. frp在穿透访问中如果不配置,header中host将采用本地Ip,remote_addr也采用本地ip,导致nextcloud无法获取想要的地址,php中redirect和location到错误地址。

[nextcloud]
 type = https
 #nextcloud服务外网端口
 local_port=10090
 #内网nextcloud所在机器ip
 local_ip=192.168.1.100
 #访问nextcloud的外网域名
 custom_domains = xxxx.com
 #采用frp插件
 plugin = https2http
 #内网nextcloud访问地址
 plugin_local_addr = 192.168.1.100:80
 # HTTPS 证书相关的配置
 plugin_crt_path = /usr/local/frp/xxxxx.com/live/fullchain.pem
 plugin_key_path = /usr/local/frp/xxxx.com/live/privkey.pem

 #nextcloud服务外网访问域名含端口
 plugin_host_header_rewrite = xxxx.com:10090
 #传递frp服务端ip地址
 plugin_header_X-From-Where = frp

2.nextcloud ini设置

修改 ./nextcloud/config/config.php

//将域名填进信任域名列表中
'trusted_domains' =>
     array (
     0 => 'xxxx.com:10090',
     1 => '192.168.1.100',
     2 => 'www.xxxx.com:10090'
 ),
/**
*将frps地址加入信任代理列表,nextcloud从headerzhong`X-Forwarded-For`获取的替代`REMOTE_ADDR`,支持正则表达式
*List of trusted proxy servers
client IP will be read from the HTTP header specified in
`forwarded_for_headers` instead of from `REMOTE_ADDR`.
* Defaults to an empty array.
*/
 'trusted_proxies' => ['10.10.10.100','192.168.1.100'],
 /**
 * 设置改写条件地址,满足条件的地址可以使用`overwriteprotocol`等配置
 * This option allows you to define a manual override condition as a regular
 * expression for the remote IP address. For example, defining a range of IP
 * addresses starting with ``10.0.0.`` and ending with 1 to 3:
 * ``^10\.0\.0\.[1-3]$``
 *
 * Defaults to ``''`` (empty string)
 */
 'overwritecondaddr' => '^10\.10\.100\.100$',
 /**
 * 重写访问协议,因为frp中httpshttp会传输http访问地址导致跳转失败
 * When generating URLs, Nextcloud attempts to detect whether the server is
 * accessed via ``https`` or ``http``. However, if Nextcloud is behind a proxy
 * and the proxy handles the ``https`` calls, Nextcloud would not know that
 * ``ssl`` is in use, which would result in incorrect URLs being generated.
 * Valid values are ``http`` and ``https``.
 */
 'overwriteprotocol' => 'https',

3.nextcloud 文件修改

修改./lib/private/AppFramework/Http/Request.php文件中isOverwriteCondition函数。nextcloud在isOverwriteCondition采用的$remoteAddr仍然为 $this->server['REMOTE_ADDR'],导致后续比较失败,不知后续版本是否有更正。

private function isOverwriteCondition(string $type = ''): bool {
$regex = '/' . $this->config->getSystemValue('overwritecondaddr', '')  . '/';
//$remoteAddr = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : '';
//采用`X-Forwarded-For`中地址
$remoteAddr = $this->getRemoteAddress();
return $regex === '//' || preg_match($regex, $remoteAddr) === 1
         || $type !== 'protocol';
}