当前位置: 首页 > news >正文

yii2项目使用frp https2http插件问题

yii2内网项目,使用frp进行内网穿透,使用 https2http插件把内网服务器http流量转成https,会存在一个问题:当使用 $this->redirect(...) 或 $this->goHome() (其实用的也是前者)等重定向时,网址会变成 127.0.0.1,并且协议也从https变成了 http,结果自然是显示找不到

frp client配置类似官网例子:

[common]
server_addr = 47.xx.xxx.xx
server_port = 7900[web_https]
type = https
custom_domains = lab.xxxxx.complugin = https2http
plugin_local_addr = 127.0.0.1:80plugin_crt_path = ./xxxxx.com.pem
plugin_key_path = ./xxxxx.com.key
plugin_host_header_rewrite = 127.0.0.1
plugin_header_X-From-Where = frp

比较通过域名 https://lab.xxxxx.com:8900 访问和通过IP地址访问时 $_SERVER 超级全局变量的结果差异,主要有以下差异:

$_SERVER = Array
([HTTP_X_FROM_WHERE] => frp[HTTP_X_FORWARDED_FOR] => 47.xx.xxx.xx[HTTP_SEC_FETCH_USER] => ?1[HTTP_SEC_FETCH_SITE] => same-origin[HTTP_SEC_FETCH_MODE] => navigate[HTTP_SEC_FETCH_DEST] => document[HTTP_SEC_CH_UA_PLATFORM] => "Linux"[HTTP_SEC_CH_UA_MOBILE] => ?0[HTTP_SEC_CH_UA] => "Chromium";v="110", "Not A(Brand";v="24", "Google Chrome";v="110"[HTTP_REFERER] => https://lab.xxxxx.com:8900/[HTTP_HOST] => 127.0.0.1[SERVER_ADDR] => 127.0.0.1[REMOTE_ADDR] => 127.0.0.1
)
$_SERVER = Array
([HTTP_CONNECTION] => keep-alive[HTTP_HOST] => 10.5.10.200[SERVER_ADDR] => 10.5.10.200[REMOTE_ADDR] => 10.5.21.241
)

前一个是frp代理后的结果,后一个是内网直接访问的结果,我们用下图来表示这个过程

用frp内网穿透,是某种形式的反向代理。frp server只起到转发作用,它的配置非常简单,也就指定一下“主控”端口和https监听端口。使用https2http插件时,证书是配置在frp client的(即需要把通常放在公网frp server服务器的证书放一份在frp client,这里也说明frp只适合绝对信得过的client使用该插件)。frp client 上的证书,既用于frp server转发过来的流量的解密(变成http流量转发给nginx),也用于nginx响应的流量的加密(变成https流量转发给frp server,并最终响应给用户)。

我们可以发现,对于nginx来说,它的“客户”是frp client,从IP地址来说,这里的frp client “客户”地址(REMOTE_ADDR)和这里的 server nginx地址(SERVER_ADDR)都是127.0.0.1,相当于“客户”frp client,主机Host也是 127.0.0.1。不过头部中的主机信息 HTTP_HOST 是可以被重写的,对于 http 代理是配置 host_header_rewrite,而对于我们的 https2http插件,需要在 frp client配置 plugin_host_header_rewrite来重写主机Host信息。(frp client中配置 plugin_header_X-xxxx-xxx形式的头部信息,对应了 HTTP_X_xxxx_xxx 形式的头部,只是在我们的情形中,配置 HTTP_HOST、HTTP_X_FORWARDED_HOST、HTTP_PROTO、HTTP_X_FORWARDED_PORT等都不能解决问题)

了解了frp代理的基本原理,我们需要来了解yii2中redirect是怎么进行的。

yii2 redirect 所需的URL信息可以分为两个部分:第一部分是 协议、主机、端口,这部分根据yii\web\Request::getHostInfo() 函数确定;第二部分是相对于文档根的路径,由 Url::to($url)计算得到。我们关心前面的部分,代码如下

    public function getHostInfo(){if ($this->_hostInfo === null) {$secure = $this->getIsSecureConnection();$http = $secure ? 'https' : 'http';if ($this->getSecureForwardedHeaderTrustedPart('host') !== null) {$this->_hostInfo = $http . '://' . $this->getSecureForwardedHeaderTrustedPart('host');} elseif ($this->headers->has('X-Forwarded-Host')) {$this->_hostInfo = $http . '://' . trim(explode(',', $this->headers->get('X-Forwarded-Host'))[0]);} elseif ($this->headers->has('X-Original-Host')) {$this->_hostInfo = $http . '://' . trim(explode(',', $this->headers->get('X-Original-Host'))[0]);} elseif ($this->headers->has('Host')) {$this->_hostInfo = $http . '://' . $this->headers->get('Host');} elseif (isset($_SERVER['SERVER_NAME'])) {$this->_hostInfo = $http . '://' . $_SERVER['SERVER_NAME'];$port = $secure ? $this->getSecurePort() : $this->getPort();if (($port !== 80 && !$secure) || ($port !== 443 && $secure)) {$this->_hostInfo .= ':' . $port;}}}return $this->_hostInfo;}

代码的基本执行路径如下:

解决方案一:

frp client配置中,指定

 plugin_host_header_rewrite = lab.xxxxx.com:8900

这样,frp client 转发到 nginx 时,头部信息 HTTP_HOST 会被改写成设定的值,从而 getHostInfo 执行时会走路径4 (读取头部 Host信息的紫色路径),但仅仅这样是不行的,因为我们需要协议是 https,而 getIsSecureConnection 根据超级全局变量 $_SERVER['HTTPS'] 或者头部信息Forwarded中的proto部分来决定是https还是http(转发时不存在https到http切换会比较简单,因为不需要考虑这一步)。我们一种变通方法是在 yii2 入口文件中,直接指定 $_SERVER['HTTPS']=1(当然,为了兼容内网ip地址访问,可以判断 $_SERVER['SERVER_ADDR']和$_SERVER['REMOTE_ADDR']是否同时为127.0.0.1,因为我们的自我转发中,这是特点)

if ($_SERVER['SERVER_ADDR'] === '127.0.0.1' && $_SERVER['REMOTE_ADDR'] === '127.0.0.1') {  // 是内网穿透自身代理而来的请求$_SERVER['HTTPS'] = '1';  //
}
$application->run();

解决方案二:

frp client配置中,不指定 plugin_host_header_rewrite,但额外指定

plugin_header_Forwarded = for=47.xx.xxx.xx;host=lab.xxxxx.com:8900;proto=https

然后在 yii2 的配置中,对组件 request 添加配置(下面 baseUrl后面部分)

            'baseUrl' => '/admin',  //-----------后端基础目录'trustedHosts' => [  // https://www.yiiframework.com/doc/api/2.0/yii-web-request#$secureHeaders-detail'127.0.0.1/24',  // 从代理转发的,这里设置白名单,这样 $secureHeaders 中的 X-Forwarded-Host 等头部才被允许],'secureHeaders' => [  // frp配置: plugin_header_Forwarded = 'Forwarded',    // 我们添加的 集合了各项 forwarded, 参考 yii\web\Request::getSecureForwardedHeaderParts()'X-Forwarded-For','X-Forwarded-Host','X-Forwarded-Proto','X-Forwarded-Port','Front-End-Https','X-Rewrite-Url','X-Original-Host',],

这样配置后,frp client 转发时会带上头部 Forwarded,并且这个Forwarded头部将被 yii2 允许(转发主机白名单,可接受头部等)。从而,代码执行流程会按前面图中红色路径走。

路径2、3、5也可以考虑,不过和第一个方案一样,需要指定 $_SERVER['HTTPS'] = 1来指定协议,而且端口不一定好处理。

相关文章:

yii2项目使用frp https2http插件问题

yii2内网项目,使用frp进行内网穿透,使用 https2http插件把内网服务器http流量转成https,会存在一个问题:当使用 $this->redirect(...) 或 $this->goHome() (其实用的也是前者)等重定向时,…...

关于 interface{} 会有啥注意事项?下

我们一起来回顾一下上一次说到的 interface{} 可以用来做多态 接口类型分为空接口类型和非空接口类型,他们的底层数据结构不太一样 这里顺便说一下,用来作态需要满足这样的条件: 首先得有父类指针指向子类的对象这个接口还必须是非空接口…...

ansible组件介绍和简单playbook测试

一、ansible inventory 在大规模的配置管理工作中,管理不同业务的机器,机器的信息都存放在ansible的inventory组件里面。在工作中,配置部署针对的主机必须先存放在Inventory里面,然后ansible才能对它进行操作。默认的Ansible的in…...

[数据结构]:13-插入排序(顺序表指针实现形式)(C语言实现)

目录 前言 已完成内容 插入排序实现 01-开发环境 02-文件布局 03-代码 01-主函数 02-头文件 03-PSeqListFunction.cpp 04-SortCommon.cpp 05-SortFunction.cpp 结语 前言 此专栏包含408考研数据结构全部内容,除其中使用到C引用外,全为C语言代…...

es6 new Promise

Promise 是一个构造函数,本身身上有 all、reject、resolve 这几个方法,原型上有 then、catch 等方法。所以 Promise new 出来的对象确定就有 then、catch 方法。Promise 的构造函数接收一个参数,是函数,而且传入两个参数&#xff…...

Python爬虫实战:使用Requests和BeautifulSoup爬取网页内容

标题:Python爬虫实战:使用Requests和BeautifulSoup爬取网页内容 Python爬虫技术是网络爬虫中的一种,它可以从互联网上抓取各种网页信息,如文本、图片、视频等,并将它们存储在本地数据库中。Python语言具有简单易学、语…...

质量指标——什么是增量覆盖率?它有啥用途?

目录 引言 什么是增量覆盖率 增量覆盖率有啥用途 1、对不同角色同学的用途 2、对不同规模的业务需求的用途 增量覆盖率的适用人员 增量覆盖率不太适用的情况 引言 有些质量团队,有时会拿「增量覆盖率」做出测试的准出卡点。 但在实际的使用过程中,…...

Hive---拉链表

拉链表 文章目录拉链表定义用途案例全量流程增量流程合并过程第一步第二步第三步案例二(含分区)创建外部表orders增量分区表历史记录表定义 拉链表是一种数据模型,主要是针对数据仓库设计中表存储数据的方式而定义的,顾名思义&am…...

日常文档标题级别规范

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…...

C++学习记录——십이 vector

文章目录1、vector介绍和使用2、vector模拟实现insert和erase和迭代器失效补齐其他函数深浅拷贝难点思考1、vector介绍和使用 vector可以管理任意类型的数组&#xff0c;是一个表示可变大小数组的序列容器。 通过vector文档来看它的使用。 #include <iostream> #inclu…...

Lombok常见用法总结

目录一、下载和安装二、常见注释&#xff08;一&#xff09;Data&#xff08;二&#xff09;Getter和Setter&#xff08;三&#xff09;NonNull和NotNull&#xff08;不常用&#xff09;&#xff08;四&#xff09;ToString&#xff08;不常用&#xff09;&#xff08;五&#…...

【Ajax】异步通信

一.概述 概念&#xff1a;AJAX(Asynchronous JavaScript And XML)&#xff1a;异步的 JavaScript 和 XML 作用&#xff1a; 与服务器进行数据交换&#xff1a;通过AJAX可以给服务器发送请求&#xff0c;并获取服务器响应的数据 使用了AJAX和服务器进行通信&#xff0c;就可以使…...

近红外吸收荧光染料IR-808,IR-808 NH2,IR-808 amine,发射808nm 性质分享

中文名称&#xff1a;IR-808 氨基英文名称&#xff1a;IR-808 NH2&#xff0c;IR-808 amine&#xff0c;IR-808-NH2规格标准&#xff1a;10mg&#xff0c;25mg&#xff0c;50mgCAS&#xff1a;N/A产品描述&#xff1a;IR-808&#xff0c;发射808nm&#xff0c;酯溶性染料修饰氨…...

一图来看你需要拥有那些知识储备

技术实践 数据 关系型数据 MySQLSQLServerOraclePostgrSQLDB2 大数据存储 RedisMemcacheMongoDBHBaseHive 大数据处理 Hadoop 数据报表看板 DataGearGrafanaKibanaMetaBase 消息对列 Rabbit MQRock MQActive MQKafka 大数据搜索 SolrElasticSearchLucenHive 服务提…...

复位和时钟控制(RCC)

目录 复位 系统复位 电源复位 备份区复位 时钟控制 什么是时钟&#xff1f; 时钟来源 二级时钟源: 如何使用CubeMX配置时钟 复位 系统复位 当发生以下任一事件时&#xff0c;产生一个系统复位&#xff1a;1. NRST引脚上的低电平(外部复位) 2. 窗口看门狗计数终止(WWD…...

OpenWrt 专栏介绍00

文章目录OpenWrt 专栏介绍00专栏章节介绍关于联系方式OpenWrt 专栏介绍00 专栏章节介绍 本专栏主要从开发者角度&#xff0c;一步步深入理解OpenWrt开发流程&#xff0c;本专栏包含以下章节&#xff0c;内如如下&#xff1a; 01.OperWrt 环境搭建02.OperWrt 包管理系统03.Op…...

udk开发-稀里糊涂

一、EDK2简介 1.EDK2工作流 ​ 二、EDK2 Packages 1.Packages介绍 ​ EDK2 Packages是一个容器&#xff0c;其中包含一组模块及模块的相关定义。每个Package是一个EDK2单元。 整个Project的源代码可以被分割成不同的Pkg。这样的设计不仅可以降低耦合性&#xff0c;还有利于分…...

Java之内部类

目录 一.内部类 1.什么是内部类 2.内部类存在的原因 3. 内部类的分类 4.内部类的作用 二.成员内部类 1.基本概念 2.成员内部类的注意点 1.成员内部类可以用private方法进行修饰 2.成员内部类可以直接访问外部类的私有属性 3.外部类可以通过对象访问内部类的私有属性 …...

【MyBatis】篇二.MyBatis查询与特殊SQL

文章目录1、MyBatis获取参数值case1-单个字面量类型的参数case2-多个字面量类型的参数case3-map集合类型的参数case4-实体类类型的参数case5-使用Param注解命名参数总结2、MyBatis的各种查询功能case1-查询结果是一个实体类对象case2-查询结果是一个List集合case3-查询单个数据…...

CE认证机构和CE证书的分类

目前&#xff0c;CE认证已普遍被应用在很多行业的商品中&#xff0c;也是企业商品进入欧洲市场的必备安全合格认证。在船舶海工行业中&#xff0c;也同样普遍应用&#xff0c;很多时候&#xff0c;对于规范中没有明确认证要求的设备或材料&#xff0c;而船舶将来还会去欧洲水域…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...

算法打卡第18天

从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7…...

WEB3全栈开发——面试专业技能点P4数据库

一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库&#xff0c;基于 mysql 库改进而来&#xff0c;具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点&#xff1a; 支持 Promise / async-await&#xf…...