PHP 服务挂了之后是不是就能查看. PHP 文件源码了?

2021-10-21 18:15:20 +08:00
 ysy950803

问个小白问题,有这么一个场景,假如我把.php 文件放在网站目录下,和 index.html 同目录,可通过浏览器访问的那种。 比如有一个 test.php 文件,里面有一些 PHP 代码,不渲染任何东西,当服务正常的时候,浏览器显示空白,这是正常情况。但如果 fpm 等相关服务挂掉了,是不是再访问就直接视为普通文本文件返回给浏览器了?这样就能看见源码了?

8744 次点击
所在节点    PHP
115 条回复
fkdtz
2021-10-26 16:57:28 +08:00
楼主你惹祸了
hxy100
2021-10-26 17:41:39 +08:00
@ysc3839 你的这个说法我认同,而且我知道你这个回答是看了我帖子的其他回复给出的答案,我确实是做了强关联,我接受,这是我的狭隘之处,我也知道,后缀名!=文件类型!=MIME type (我上面的其中一个回复里面举例时也提到了这一点),但绝大多数时候,我们如果没有特殊需求,往往就是采用开宗明义的做法,以后缀名区分文件类型,然后再以不同的文件类型作为标识输出给浏览器 [MIME Type] ,这种情况下,后缀名间接对应 MIME Type ,PHP 同样也有,大概总结就是 Web 服务把不同后缀的文件类型区分,该读取的读取,该由第三方解析的解析,然后统一回复客户端,不仅仅是静态资源文件有,有的 Web Server 会明示某种动态脚本后缀的文件为某个 MIME Type (比如 Apache 定义 PHP 为 application/x-httpd-php ),有的 Web Server 不明示,但不代表内部的这种 Type 区分不存在。我上面要强调的是仅仅是不同文件类型的区分,在任何一个流行的 Web Server ( Nginx ,Apache ,IIS ,LightHttpd 等等)都是存在的,不管你看不看得见。配置 PHP 时正确配置这个 Type ,不管后端接盘的 php-fpm 还是其他的何方神圣,都不会暴露源码。

-----

综上,我认为我的表述过于狭隘,或者说不应该把服务端的这种区别文件类型的做法叫 MIME Type ,MIME Type 严格的描述应该是 xxx/xxxxx 这样的形式,至于其余的逻辑没问题,我理解 Web Server 是怎么处理各种文件的。你的这条回答很中肯。我也虚心接受,不像 @void1900 一顿乱杠,自己的逻辑里面很多东西都是错的。
void1900
2021-10-26 17:53:56 +08:00
@hxy100 还在杠

不管我文件名是不是.php ,mime type 配不配 application/x-httpd-php

我都能让他走 php cgi 解析,这种情况配对了吗?

我起名叫 .nb , mime types 配置 text/nb ,

我只要配置了 nginx 的 proxy_pass 或者 apache 的 SetHandler ,就能解析,这种怎么解释,你还能扯扩展名和 mime type 吗?

还我一顿乱杠,666
hxy100
2021-10-26 18:10:03 +08:00
@void1900 我不回复你了,只有楼上这位仁兄 @ysc3839 认真看了我的答案,你的话就只顾自说自话,我不知道你是从来不看别人这么说,还是我答得太长了,你有点晕看不懂,你不会正视自己的问题,就只想证明别人是错的,你再从头把我的每一个回复看一遍,我什么时候说过只要 inlcude mime.types 和 AddType 就行了,就能正确解析了,这完全是你自己说的,我说的是所有 PHP 文件默认是一个 Type ,你给找个 Type 指定合适的规则,就完全不用担心爆不爆源码的文件。爆不爆源码与后端服务的死活无关,只与 Web 服务器本身有关,Web 服务器就是靠这个 Type 来区分文件的,这个 Type 可以是.php ,也可以是.abc ,web 服务器认得就是这个 Type ,你可以把 .php .123 .abc 这三个后缀的文件合并成一组交给后端解析,组名也就是这个 Type ,我之前叫这个叫 MIME Type 可能有误,直接就叫文件类型标识好了。
void1900
2021-10-26 18:25:33 +08:00
@hxy100 我都和你说了,和 mime type 也好 扩展名也好都没有关系,还在这硬扯 type 。

你的第一个回答就是 “只要你 MIME type 配置正确”
void1900
2021-10-26 18:29:11 +08:00
@hxy100

还说 "除非你把.php 后缀的文件配置成 txt 形式( text/plain )加载,这样无论服务挂不挂都会暴露源码。"

我就算这样设置,吧文件转发给 cgi 一样不暴露。能理解吗?

还在硬扛
hxy100
2021-10-26 19:22:06 +08:00
@void1900 我说的有什么问题,我说的“配置正确”范围很宽泛,不管你配置转发到后端也好,或者配置权限控制也好(密码访问,IP 限制等),哪怕是 Nginx 你这么写 location ~ *.php {deny alll;},我都都算配置正确。我说的“配置正确”意思就是叫你对这类文件的预期行为进行设置,如果你设置有误,设置成纯文本模式读取的形式( text/plain,text/css 等),或者没设置设置成未知的类型,那 MIME Type 默认就是 application/octet-stream ,这样 http 访问就会被当成一个附件下载下来了,不管 HTTP header 输不输出这个 Content-type 头,只要 Web 服务器认为这个文件不需要被处理,需要输出原始流,都会导致源码暴露。你才是硬杠,我提这个的东西最初衷的目的就是让题主去了解服务器分文件类型解析和输出结果的过程,然后题主就不会有这样的疑问了,因为 php 这个文件类型已经被约定行为了。你可以说 PHP 文件在 Web 服务器内部不能叫 MIME Type ,我叫错了,但你无法证明我的思路和阐述是错误的,就这样子。
void1900
2021-10-26 19:46:15 +08:00
@hxy100 对你说的都对
hxy100
2021-10-26 19:48:32 +08:00
@void1900 很好,结贴
liuxu
2021-10-27 00:08:46 +08:00
@jindeq
@void1900
@hxy100

直接用 nginx 源码讲话。


首先说明 nginx 的默认配置 mime.types ,内容如:
types {
text/html html htm shtml;
text/css css;
text/xml xml;
...

存储在 nginx 内存中方存放的方式为:
[
'html' => 'text/html',
'htm' => 'text/html',
'shtml' => 'text/html',
'css' => 'text/css',
'xml' => 'text/xml',
...
]
也就是['ext' => 'mime']这种格式,从这里就很清楚了,mime 和文件后缀可以互相替代,但是 mime 不是文件后缀,你完全可以在这个文件里添加一条
text/html v2ex;

此后后缀为".v2ex"的文件 nginx 返回时 response 的 Content-type 就会设置成 text/html

liuxu@liuxu-VirtualBox:/etc/nginx$ cat mime.types | grep v2ex
text/html v2ex;

liuxu@liuxu-VirtualBox:/etc/nginx$ ls -l /var/www/html/
total 12
-rw-r--r-- 1 root root 612 10 月 26 21:47 index.nginx-debian.html
-rw-r--r-- 1 root root 11 10 月 26 23:34 test.v2ex

liuxu@liuxu-VirtualBox:/etc/nginx$ file /var/www/html/index.nginx-debian.html
/var/www/html/index.nginx-debian.html: HTML document, ASCII text

liuxu@liuxu-VirtualBox:/etc/nginx$ file /var/www/html/test.v2ex
/var/www/html/test.v2ex: ASCII text

liuxu@liuxu-VirtualBox:/etc/nginx$ cat /var/www/html/test.v2ex
I'm liuxu.

liuxu@liuxu-VirtualBox:/etc/nginx$ curl -v http://127.0.0.1/test.v2ex
* Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET /test.v2ex HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0 (Ubuntu)
< Date: Tue, 26 Oct 2021 15:35:53 GMT
< Content-Type: text/html
< Content-Length: 11
< Last-Modified: Tue, 26 Oct 2021 15:34:36 GMT
< Connection: keep-alive
< ETag: "6178200c-b"
< Accept-Ranges: bytes
<
I'm liuxu.
* Connection #0 to host 127.0.0.1 left intact



在有了以上说明后,下面从 nginx 源码说话:

1. nginx 不设置 default_type 时,response 的 Content-Type 默认是 text/plain ,而不是 application/octet-stream 。也就是说单独一个 nginx 运行,root 目录为 /var/www/html/时,把 test.php 放入 /var/www/html/下,会直接打印代码。

https://github.com/nginx/nginx/blob/41a241b3ef74dbbe3d82ab2ebbe682919e4a0b90/src/http/ngx_http_core_module.c#L3693

2. nginx 设置了 default_type 为 application/octet-stream ,按 1 的配置,浏览器访问 1.php ,Content-Type 因为是 application/octet-stream 所以会下载该文件。当然也不止 application/octet-stream ,还有如果有 Content-Disposition 的话也会调用下载任务。
https://en.wikipedia.org/wiki/MIME

3. nginx 引入了自己的默认配置文件 mime.types 后,ngx_http_set_content_type()首先走到 1606 行判断有没有文件后缀,如果有后缀,则会走到 1633 ,从后缀中搜索 type ,也就是前面说的在 nginx 内存结构中的 mime.types:
type = ngx_hash_find(&clcf->types_hash, hash,
r->exten.data, r->exten.len)
if (type) {
r->headers_out.content_type_len = type->len;
r->headers_out.content_type = *type;

return NGX_OK;
}
但是由于 mime.types 中没有 php 相关的配置,也就是不存在一个"type/xxx php"这样的配置,所以如果没有设置 location ~ \.php${...}这类配置,php 文件就会被下载。

以下是返回 response 的代码:
https://github.com/nginx/nginx/blob/41a241b3ef74dbbe3d82ab2ebbe682919e4a0b90/src/http/ngx_http_core_module.c#L1593



所以 nginx 并没有通过 mime 来区分返回 response ,而是通过文件后缀查询到了对应的 mime ,然后设置了到 Content-type 然后返回。

最后说一下 location ~ \.php${...}中,.php 是不是后缀匹配。从人为理解来说是匹配.php 后缀文件,但是从 nginx 的角度来看,它就是一个正则字符串,并没有在内部 mime 列表中查出一个['php'=>'type/php']这种东西。
void1900
2021-10-27 07:43:55 +08:00
@liuxu 你就别刺激他了
lap510200
2021-10-27 09:31:52 +08:00
nginx 本身无法执行 php, 如果没有配置 php 解析或模块,php 文件又可读,是会返回源码的。如果配置了解析,nginx 碰到 php 文件会去找 fpm, 此时 fpm 挂了 ,nginx 返回是 5xx 错误。 同理对于代理转发的也是,代理的端口服务挂了也是 5xx
hxy100
2021-10-27 11:37:49 +08:00
@liuxu 你的这个回答恰恰说明了 php 会不会暴露源码跟 MIME Type 高度相关,而不是不相关,打了不少人的脸,@void1900 首当其冲,脸都被打肿了。先不讨论你回答的正确性(因为我懒得验证),根据你的回答,我阐述有问题的地方仅有两个:
一. 不是所有的 Web 服务器默认 MIME Type 都是 application/octet-stream ;
二。不能把 Nginx 通过 location 配置 PHP 解析的方式统一叫成后缀名或 MIME Type 识别,它可能仅仅就是一个 URL 路径的正则匹配。

----
当然,现在的我仍然坚持后缀名≈MIME Type 的观点,我不是说他们概念和定义相等,是说他们对 Web 服务器的影响差不多,前后端搭配,不仅是浏览器需要 Content-Type ,Web 服务器本身也需要区分哪些文件需要处理,哪些文件是直接输出。

你说的“但是从 nginx 的角度来看,它就是一个正则字符串,并没有在内部 mime 列表中查出一个['php'=>'type/php']这种东西。”这个问题我上面的回复说过了,不需要输出给浏览器特殊标头( Content-Type )的文件,并不需要显式定义,因为不管是 php ,还是 jsp 他们最终呈现给浏览器都是 text/html 而已,但不意味着在 Web 服务器内部没有一个标识来把这些 php 文件统一归类,有可能这个东西不能叫 MIME Type (你可以叫 proxy file group1 ,proxy file group2 或其他),但绝对存在这样一个标识,Nginx 这样的代理服务器也不例外。

综上,结论就是 PHP 爆不爆源码还真的跟 MIME Type 有关系。别吵了。
hxy100
2021-10-27 12:15:07 +08:00
@liuxu 另外说一下,关于第二个问题,Nginx 使用 location 配置 php 时,实际上已经在正则表达式里边传递 php 的后缀名了,所以说成是后缀名匹配也无大的错误。
void1900
2021-10-27 13:07:29 +08:00
@hxy100

都懒得理你了,你还说打我脸,怎么看都是打你脸,还高度相关,哥么别出来秀了,丢脸了
hxy100
2021-10-27 14:07:14 +08:00
@void1900 你就继续掩耳盗铃吧。你再好好读读楼上那位兄弟的回答,假如你能理解的话。要是读不懂,那我就送你三个字:“你赢了!”,散会
hxy100
2021-10-27 14:26:31 +08:00
@void1900 还有指明一点,别人的回答你都不仔细看,甚至没弄明白别人说的是什么就率先站出来反对,你看看我在这个帖子下的所有的回复,哪一个兄弟的回复的答案我没看?并且是有人给出自己观点,我都会对照自己的表述一一回应,错了就错了,概念错误,还是逻辑错误,又或者是意思没表达清楚,我都大方承认,就你光在这自说自话,压根不管别人说的是啥,这是一个学习者该有的态度吗?
-----
顺便说一句,V2 发帖的好处是无法删帖无法修改,究竟打了谁的脸,就留给观众老爷们评判吧,让时间说话。
void1900
2021-10-27 14:35:58 +08:00
@hxy100

哈哈哈哈哈 楼上多少位都和你说了 和 mime 没关系,就算你扯上扩展名也没用。

和扩展名也没有关系,真的懒得和你说了,井底之蛙应该就是说你这种人了。

还我不理解,你语文真的也不行,哥么,你找个人帮你读读。

人家结尾都说了 “并没有在内部 mime 列表中查出一个['php'=>'type/php']这种东西。”。

写正则用的是扩展名,那假如我将整个目录都 proxy_pass 给 fpm 呢?你还怎么扯你的扩展名?

还整天一个劲的总结,“就这样”,“别吵了”,看得出你很想赢。

可是技术逻辑就是那么严谨,你怎么掰扯都没有用啊,说越多越显得你可笑
void1900
2021-10-27 14:40:03 +08:00
@liuxu 你写太长了,你就和 @hxy100 说结论吧,他语文不太好。
miencun
2021-10-27 14:47:40 +08:00
Apache 模块:只能 AddType application/x-httpd-php .php ,结论:有关
CGI 模式:所谓的 Mime 可以任意起名,结论:无关
反代:不需要 Mime

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/809602

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX