蚊章汇 - http
type: channel
link: https://linuxcn.bwsl.wang/tag/http/
items: httpx：一个 Python Web 客户端
items: 借助 HTTP 通过 SSH 绕过 Linux 防火墙
items: HTTP 简史
items: 使用 gorilla/mux 进行 HTTP 请求路由和验证
items: 如何在 Linux 中快速地通过 HTTP 提供文件访问服务
items: 如何使用 Apache Web 服务器配置多个站点
items: 漫游 HTTP/2
items: PHP 、Python 等网站应用惊爆远程代理漏洞：httpoxy
items: 451：对不起，从法律上说，它不存在
items: Linux 命令行下嗅探 HTTP 流量的工具：httpry

httpx：一个 Python Web 客户端
type: item
date: 2022-03-13T18:20:49+08:00
description: Python 的 httpx 包是一个用于 HTTP 交互的一个优秀且灵活的模块。Python 的 httpx 包是一个复杂的 Web 客户端。当你安装它后，你就可以用它来从网站上获取数据。像往常一样，安装它的最简单方法是使用 pip 工具：$ python -m pip install httpx --user 要使用它，把它导入到 Python 脚本中，然后使用 .get 函数从一个 web 地址获取数据：import httpx result = httpx.get("https://httpbin.org/get?hello=world") result.json()["args"] 下面是这个简单脚本的输出： {'hello': 'world'} HTTP 响应默认情况下，httpx 不会在非 200 状态下引发错误。试试这个代码：result = httpx.get("https://httpbin.org/status/404") result 结果是： <Response [404 NOT FOUND]> 可以明确地返回一个响应。添加这个异常处理：try: result.raise_for_status() except Exception as exc: print("woops", exc) 下面是结果： woops Client error '404 NOT FOUND' for url 'https://httpbin.org/status/404' For more information check: https://httpstatuses.com/404 自定义客户端除了最简单的脚本之外，使用一个自定义的客户端是有意义的。除了不错的性能改进，比如连接池，这也是一个配置客户端的好地方。例如, 你可以设置一个自定义的基本 URL：client = httpx.Client(base_url="https://httpbin.org") result = client.get("/get?source=custom-client") result.json()["args"] 输出示例： {'source': 'custom-client'} 这对用客户端与一个特定的服务器对话的典型场景很有用。例如，使用 base_url 和 auth，你可以为认证的客户端建立一个漂亮的抽象：client = httpx.Client( base_url="https://httpbin.org", auth=("good_person", "secret_password"), ) result = client.get("/basic-auth/good_person/secret_password") result.json() 输出： {'authenticated': True, 'user': 'good_person'} 你可以用它来做一件更棒的事情，就是在顶层的 “主” 函数中构建客户端，然后把它传递给其他函数。这可以让其他函数使用客户端，并让它们与连接到本地 WSGI 应用的客户端进行单元测试。def get_user_name(client): result = client.get("/basic-auth/good_person/secret_password") return result.json()["user"] get_user_name(client) 'good_person' def application(environ, start_response): start_response('200 OK', [('Content-Type', 'application/json')]) return [b'{"user": "pretty_good_person"}'] fake_client = httpx.Client(app=application, base_url="https://fake-server") get_user_name(fake_client) 输出： 'pretty_good_person' 尝试 httpx请访问 python-httpx.org 了解更多信息、文档和教程。我发现它是一个与 HTTP 交互的优秀而灵活的模块。试一试，看看它能为你做什么。via: https://opensource.com/article/22/3/python-httpx作者：Moshe Zadka 选题：lujun9972 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出

借助 HTTP 通过 SSH 绕过 Linux 防火墙
type: item
date: 2020-08-11T07:18:39+08:00
description: 需要远程工作的看一下。使用这个有用的开源解决方案，从任何地方快速地连接和访问你的所有设备。随着对连接和远程工作的需求的增长，访问远程计算资源变得越来越重要。但是，提供对设备和硬件的外部访问的要求使此任务变得复杂而有风险。旨在减少此类麻烦的 ShellHub 是一个云服务器，允许从任何外部网络常规访问这些设备。ShellHub 是一个 Apache 2.0 许可的开源解决方案，它可满足所有这些需求，并允许用户通过一个帐户连接和管理多个设备。它的开发是为了方便开发者和程序员的工作，使得任何硬件架构的 Linux 设备的远程访问成为可能。仔细观察，ShellHub 方案使用 HTTP 传输层来封装 SSH 协议。这种传输层的选择可以在大多数网络上无缝使用，因为大多数公司的防火墙规则和策略通常都可以使用并接受它。下面这些示例使用 2020 年 6 月 10 日发布的 ShellHub 版本 0.3.2。使用 ShellHub要访问该平台，只需进入 shellhub.io 并注册一个自己的帐户。你的注册数据将帮助开发团队了解用户资料并提供有关如何改进平台的更多信息。图 1：shellhub.io 中的注册表格ShellHub 有直观、简洁的界面，这让所有的信息和功能都能以最快的方式呈现。注册后，你会看到一块仪表板，这时可以注册你的第一台设备。添加设备要启用通过 ShellHub 连接设备，你需要生成一个标识符，它用于在设备连接到服务器时对你的设备进行身份验证。此标识必须配置在代理（ShellHub 客户端）内部，该代理必须与镜像一起保存在设备中，或者必须添加为 Docker 容器。ShellHub 默认使用 Docker 运行代理，这非常方便，因为它在现有系统上提供了一种无痛的添加方式，支持 Docker 是唯一的要求。要添加设备，你需要粘贴命令行，它显示在 ShellHub Cloud 的对话框中（请参见图 2）。图 2：将设备添加到 ShellHub Cloud设备默认使用它的 MAC 地址作为其主机名。在内部，该设备由其密钥标识，这是在设备注册期间生成的，用于与服务器进行身份验证。访问设备要访问你的设备，只需进入仪表板中的“查看所有设备”，或单击左侧菜单上的“设备”。这将列出你所有已注册的设备。设备状态可在页面上轻松看到。在线设备旁边会显示一个绿色图标，可以单击终端图标进行连接。你接着输入密码，最后单击”连接“按钮，请参见（图 3）。图 3：使用网络上的终端访问设备另一种访问设备的方法是从类似 PuTTY、Termius 之类的 SSH 客户端，甚至 Linux 终端访问。我们可以使用称为 SSHID 的 ShellHub 标识作为连接的目的地址（例如 ssh username@SSHID）。图 4 说明了如何使用在终端中使用 Linux SSH 客户端连接到我们的计算机。图 4：使用 Linux 终端连接到设备无论你何时登录 ShellHub Cloud 平台，你都可以访问仪表板上的所有已注册设备，这样你可以随时随地访问它们。ShellHub 通过一个开源平台，以透明的方式为您与远程机器保持通信安全的过程增加了简单性。在 GitHub 上加入 ShellHub 社区，或随时通过 Gitter 或通过电子邮件 contato@ossystems.com.br 向开发团队发送你的建议或反馈。我们很乐意收到社区成员的贡献！via: https://opensource.com/article/20/7/linux-shellhub作者：Domarys 选题：lujun9972 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出

HTTP 简史
type: item
date: 2019-03-15T19:31:00+08:00
description: 译注：本文来源于 2013 年出版的《High Performance Browser Networking》的第九章，因此有些信息略有过时。事实上，现在 HTTP/2 已经有相当的不是，而新的 HTTP/3 也在设计和标准制定当中。介绍 超文本传输协议 Hypertext Transfer Protocol （HTTP）是互联网上最普遍和广泛采用的应用程序协议之一。它是客户端和服务器之间的通用语言，支持现代 Web。从最初作为单个的关键字和文档路径开始，它已成为不仅仅是浏览器的首选协议，而且几乎是所有连接互联网硬件和软件应用程序的首选协议。在本文中，我们将简要回顾 HTTP 协议的发展历史。对 HTTP 不同语义的完整讨论超出了本文的范围，但理解 HTTP 的关键设计变更以及每个变更背后的动机将为我们讨论 HTTP 性能提供必要的背景，特别是在 HTTP/2 中即将进行的许多改进。HTTP 0.9: 单行协议 蒂姆·伯纳斯·李 Tim Berners-Lee 最初的 HTTP 提案在设计时考虑到了简单性，以帮助他采用他的另一个新想法： 万维网 World Wide Web 。这个策略看起来奏效了：注意，他是一个有抱负的协议设计者。1991 年，伯纳斯·李概述了这个新协议的动机，并列出了几个高级设计目标：文件传输功能、请求超文档存档索引搜索的能力，格式协商以及将客户端引用到另一个服务器的能力。为了证明该理论的实际应用，构建了一个简单原型，它实现了所提议功能的一小部分。客户端请求是一个 ASCII 字符串。客户端请求以回车符（CRLF）终止。服务器响应是 ASCII 字符流。服务器响应是一种超文本标记语言（HTML）。文档传输完成后连接终止。然而，即使这听起来也比实际复杂得多。这些规则支持的是一种非常简单的，对 Telnet 友好的协议，一些 Web 服务器至今仍然支持这种协议：$> telnet google.com 80 Connected to 74.125.xxx.xxx GET /about/ (hypertext response) (connection closed)请求包含这样一行：GET 方法和请求文档的路径。响应是一个超文本文档，没有标题或任何其他元数据，只有 HTML。真的是再简单不过了。此外，由于之前的交互是预期协议的子集，因此它获得了一个非官方的 HTTP 0.9 标签。其余的，就像他们所说的，都是历史。从 1991 年这些不起眼的开始，HTTP 就有了自己的生命，并在接下来几年里迅速发展。让我们快速回顾一下 HTTP 0.9 的特性：采用客户端-服务器架构，是一种请求-响应协议。采用 ASCII 协议，运行在 TCP/IP 链路上。旨在传输超文本文档（HTML）。每次请求后，服务器和客户端之间的连接都将关闭。流行的 Web 服务器，如 Apache 和 Nginx，仍然支持 HTTP 0.9 协议，部分原因是因为它没有太多功能！如果你感兴趣，打开 Telnet 会话并尝试通过 HTTP 0.9 访问 google.com 或你最喜欢的网站，并检查早期协议的行为和限制。HTTP/1.0: 快速增长和 Informational RFC1991 年至 1995 年期间，HTML 规范和一种称为 “web 浏览器”的新型软件快速发展，面向消费者的公共互联网基础设施也开始出现并快速增长。完美风暴：1990 年代初的互联网热潮基于蒂姆·伯纳斯·李最初的浏览器原型，美国国家超级计算机应用中心（NCSA）的一个团队决定实现他们自己的版本。就这样，第一个流行的浏览器诞生了：NCSA Mosaic。1994 年 10 月，NCSA 团队的一名程序员 Marc Andreessen 与 Jim Clark 合作创建了 Mosaic Communications，该公司后来改名为 Netscape（网景），并于 1994 年 12 月发布了 Netscape Navigator 1.0。从这一点来说，已经很清楚了，万维网已经不仅仅是学术上的好奇心了。实际上，同年在瑞士日内瓦组织了第一次万维网会议，这导致 万维网联盟 World Wide Web Consortium （W3C）的成立，以帮助指导 HTML 的发展。同样，在 IETF 内部建立了一个并行的 HTTP 工作组 HTTP Working Group （HTTP-WG），专注于改进 HTTP 协议。后来这两个团体一直对 Web 的发展起着重要作用。最后，完美风暴来临，CompuServe，AOL 和 Prodigy 在 1994-1995 年的同一时间开始向公众提供拨号上网服务。凭借这股迅速的浪潮，Netscape 在 1995 年 8 月 9 日凭借其成功的 …

使用 gorilla/mux 进行 HTTP 请求路由和验证
type: item
date: 2018-12-15T17:10:42+08:00
description: gorilla/mux 包以直观的 API 提供了 HTTP 请求路由、验证和其它服务。Go 网络库包括 http.ServeMux 结构类型，它支持 HTTP 请求多路复用（路由）：Web 服务器将托管资源的 HTTP 请求与诸如 /sales4today 之类的 URI 路由到代码处理程序；处理程序在发送 HTTP 响应（通常是 HTML 页面）之前执行适当的逻辑。 这是该体系的草图： +-----------+ +--------+ +---------+ HTTP 请求---->| web 服务器 |---->| 路由 |---->| 处理程序 | +-----------+ +--------+ +---------+调用 ListenAndServe 方法后启动 HTTP 服务器：http.ListenAndServe(":8888", nil) // args: port & router第二个参数 nil 意味着 DefaultServeMux 用于请求路由。gorilla/mux 库包含 mux.Router 类型，可替代 DefaultServeMux 或自定义请求多路复用器。 在 ListenAndServe 调用中，mux.Router 实例将代替 nil 作为第二个参数。 下面的示例代码很好的说明了为什么 mux.Router如此吸引人：1、一个简单的 CRUD web 应用程序crud web 应用程序（见下文）支持四种 CRUD（创建/读取/更新/删除）操作，它们分别对应四种 HTTP 请求方法：POST、GET、PUT 和 DELETE。 在这个 CRUD 应用程序中，所管理的资源是套话与反套话的列表，每个都是套话及其反面的的套话，例如这对：Out of sight, out of mind. Absence makes the heart grow fonder.可以添加新的套话对，可以编辑或删除现有的套话对。CRUD web 应用程序：package main import ( "gorilla/mux" "net/http" "fmt" "strconv" ) const GETALL string = "GETALL" const GETONE string = "GETONE" const POST string = "POST" const PUT string = "PUT" const DELETE string = "DELETE" type clichePair struct { Id int Cliche string Counter string } // Message sent to goroutine that accesses the requested resource. type crudRequest struct { verb string cp *clichePair id int cliche string counter string confirm chan string } var clichesList = []*clichePair{} var masterId = 1 var crudRequests chan *crudRequest // GET / // GET /cliches func ClichesAll(res http.ResponseWriter, req *http.Request) { cr := &crudRequest{verb: GETALL, confirm: make(chan string)} completeRequest(cr, res, "read all") } // GET /cliches/id func ClichesOne(res http.ResponseWriter, req *http.Request) { id := getIdFromRequest(req) cr := &crudRequest{verb: GETONE, id: id, confirm: make(chan string)} completeRequest(cr, res, "read one") } // POST /cliches func ClichesCreate(res http.ResponseWriter, req *http.Request) { cliche, counter := getDataFromRequest(req) cp := new(clichePair) cp.Cliche = cliche cp.Counter = counter cr := &crudRequest{ver…

如何在 Linux 中快速地通过 HTTP 提供文件访问服务
type: item
date: 2018-11-07T21:22:37+08:00
description: 如今，我有很多方法来通过 Web 浏览器为局域网中的其他系统提供单个文件或整个目录的访问。我在我的 Ubuntu 测试机上测试了这些方法，它们如下面描述的那样运行正常。如果你想知道如何在类 Unix 操作系统中通过 HTTP 轻松快速地提供文件和文件夹的访问服务，以下方法之一肯定会有所帮助。在 Linux 中通过 HTTP 访问文件和文件夹免责声明：此处给出的所有方法适用于安全的局域网。由于这些方法没有任何安全机制，因此不建议在生产环境中使用它们。你注意了！方法 1 - 使用 simpleHTTPserver（Python）我们写了一篇简要的指南来设置一个简单的 http 服务器，以便在以下链接中即时共享文件和目录。如果你有一个安装了 Python 的系统，这个方法非常方便。如何使用 simpleHTTPserver 设置一个简单的文件服务器方法 2 - 使用 Quickserve（Python）此方法针对 Arch Linux 及其衍生版。有关详细信息，请查看下面的链接。如何在 Arch Linux 中即时共享文件和文件夹方法 3 - 使用 Ruby在此方法中，我们使用 Ruby 在类 Unix 系统中通过 HTTP 提供文件和文件夹访问。按照以下链接中的说明安装 Ruby 和 Rails。在 CentOS 和 Ubuntu 中安装 Ruby on Rails安装 Ruby 后，进入要通过网络共享的目录，例如 ostechnix：$ cd ostechnix并运行以下命令：$ ruby -run -ehttpd . -p8000 [2018-08-10 16:02:55] INFO WEBrick 1.4.2 [2018-08-10 16:02:55] INFO ruby 2.5.1 (2018-03-29) [x86_64-linux] [2018-08-10 16:02:55] INFO WEBrick::HTTPServer#start: pid=5859 port=8000确保在路由器或防火墙中打开端口 8000。如果该端口已被其他一些服务使用，那么请使用不同的端口。现在你可以使用 URL 从任何远程系统访问此文件夹的内容 - http:// <ip-address>:8000。要停止共享，请按 CTRL+C。方法 4 - 使用 Http-server（NodeJS）Http-server 是一个用 NodeJS 编写的简单的可用于生产环境的命令行 http 服务器。它不需要配置，可用于通过 Web 浏览器即时共享文件和目录。按如下所述安装 NodeJS。如何在 Linux 上安装 NodeJS安装 NodeJS 后，运行以下命令安装 http-server。$ npm install -g http-server现在进入任何目录并通过 HTTP 共享其内容，如下所示。$ cd ostechnix $ http-server -p 8000 Starting up http-server, serving ./ Available on: http://127.0.0.1:8000 http://192.168.225.24:8000 http://192.168.225.20:8000 Hit CTRL-C to stop the server现在你可以使用 URL 从任何远程系统访问此文件夹的内容 - http:// <ip-address>:8000。要停止共享，请按 CTRL+C。方法 5 - 使用 Miniserve（Rust）Miniserve 是另一个命令行程序，它允许你通过 HTTP 快速访问文件。它是一个非常快速、易于使用的跨平台程序，它用 Rust 编程语言编写。与上面的程序/方法不同，它提供身份验证支持，因此你可以为共享设置用户名和密码。按下面的链接在 Linux 系统中安装 Rust。在 Linux 上安装 Rust 编程语言安装 Rust 后，运行以下命令安装 miniserve：$ cargo install miniserve或者，你可以在其发布页下载二进制文件并使其可执行。$ chmod +x miniserve-linux然后，你可以使用命令运行它（假设 miniserve 二进制文件下载到当前的工作目录中）：$ ./miniserve-linux <path-to-share>用法要提供目录访问：$ miniserve <path-to-directory>示例：$ miniserve /home/sk/ostechnix/ miniserve v0.2.0 Serving path /home/sk/ostechnix at http://[::]:8080, http://lo…

如何使用 Apache Web 服务器配置多个站点
type: item
date: 2018-10-25T23:38:35+08:00
description: 如何在流行而强大的 Apache Web 服务器上托管两个或多个站点。在我的上一篇文章中，我解释了如何为单个站点配置 Apache Web 服务器，事实证明这很容易。在这篇文章中，我将向你展示如何使用单个 Apache 实例来服务多个站点。注意：我写这篇文章的环境是 Fedora 27 虚拟机，配置了 Apache 2.4.29。如果你用另一个发行版或不同的 Fedora 版本，那么你使用的命令以及配置文件的位置和内容可能会有所不同。正如我之前的文章中提到的，Apache 的所有配置文件都位于 /etc/httpd/conf 和 /etc/httpd/conf.d。默认情况下，站点的数据位于 /var/www 中。对于多个站点，你需要提供多个位置，每个位置对应托管的站点。基于名称的虚拟主机使用基于名称的虚拟主机，你可以为多个站点使用一个 IP 地址。现代 Web 服务器，包括 Apache，使用指定 URL 的 hostname 部分来确定哪个虚拟 Web 主机响应页面请求。这仅仅需要比一个站点更多的配置。即使你只从单个站点开始，我也建议你将其设置为虚拟主机，这样可以在以后更轻松地添加更多站点。在本文中，我将从上一篇文章中我们停止的地方开始，因此你需要设置原来的站点，即基于名称的虚拟站点。准备原来的站点在设置第二个站点之前，你需要为现有网站提供基于名称的虚拟主机。如果你现在没有站点，请返回并立即创建一个。一旦你有了站点，将以下内容添加到 /etc/httpd/conf/httpd.conf 配置文件的底部（添加此内容是你需要对 httpd.conf 文件进行的唯一更改）：<VirtualHost 127.0.0.1:80> DocumentRoot /var/www/html ServerName www.site1.org </VirtualHost>这将是第一个虚拟主机配置节，它应该保持为第一个，以使其成为默认定义。这意味着通过 IP 地址或解析为此 IP 地址但没有特定命名主机配置节的其它名称对服务器的 HTTP 访问将定向到此虚拟主机。所有其它虚拟主机配置节都应跟在此节之后。你还需要使用 /etc/hosts 中的条目设置你的网站以提供名称解析。上次，我们只使用了 localhost 的 IP 地址。通常，这可以使用你使用的任何名称服务来完成，例如 Google 或 Godaddy。对于你的测试网站，通过在 /etc/hosts 中的 localhost 行添加一个新名称来完成此操作。添加两个网站的条目，方便你以后不需再次编辑此文件。结果如下：127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 www.site1.org www.site2.org让我们将 /var/www/html/index.html 文件改变得更加明显一点。它应该看起来像这样（带有一些额外的文本来识别这是站点 1）： Hello World Web site 1.重新启动 HTTPD 服务器，已启用对 httpd 配置的更改。然后，你可以从命令行使用 Lynx 文本模式查看网站。[root@testvm1 ~]# systemctl restart httpd [root@testvm1 ~]# lynx www.site1.org Hello World Web site 1. <snip> Commands: Use arrow keys to move, '?' for help, 'q' to quit, '<-' to go back. Arrow keys: Up and Down to move. Right to follow a link; Left to go back. H)elp O)ptions P)rint G)o M)ain screen Q)uit /=search [delete]=history list你可以看到原始网站的修改内容，没有明显的错误，先按下 Q 键，然后按 Y 退出 Lynx Web 浏览器。配置第二个站点现在你已经准备好建立第二个网站。使用以下命令创建新的网站目录结构：[root@testvm1 html]# mkdir -p /var/www/html2注意，第二个站点只是第二个 html 目录，与第一个站点位于同一 /var/www 目录下。现在创建一个新的索引文件 /var/www/html2/index.html，其中包含以下内容（此索引文件稍有不同，以区别于原来的网站）： Hello World -- Again Web site 2.在 httpd.conf 中为第二个站点创建一个…

漫游 HTTP/2
type: item
date: 2016-09-27T06:20:00+08:00
description: 自从我写了上一篇博文之后，就再也找不到空闲时间写文章了。今天我终于可以抽出时间写一些关于 HTTP 的东西。我认为每一个 web 开发者都应该对这个支撑了整个 Web 世界的 HTTP 协议有所了解，这样才能帮助你更好的完成开发任务。在这篇文章中，我将讨论什么是 HTTP，它是怎么产生的，它的地位，以及我们应该怎么使用它。HTTP 是什么首先我们要明白 HTTP 是什么。HTTP 是一个基于 TCP/IP 的应用层通信协议，它是客户端和服务端在互联网互相通讯的标准。它定义了内容是如何通过互联网进行请求和传输的。HTTP 是在应用层中抽象出的一个标准，使得主机（客户端和服务端）之间的通信得以通过 TCP/IP 来进行请求和响应。TCP 默认使用的端口是 80，当然也可以使用其它端口，比如 HTTPS 使用的就是 443 端口。HTTP/0.9 - 单行协议 (1991)HTTP 最早的规范可以追溯到 1991 年，那时候的版本是 HTTP/0.9，该版本极其简单，只有一个叫做 GET的请求方式。如果客户端要访问服务端上的一个页面，只需要如下非常简单的请求：GET /index.html 服务端对应的返回类似如下：(response body) (connection closed) 就这么简单，服务端捕获到请求后立马返回 HTML 并且关闭连接，在这之中没有 头信息 （ headers ） 仅支持 GET 这一种请求方法必须返回 HTML如同你所看到的，当时的 HTTP 协议只是一块基础的垫脚石。HTTP/1.0 - 1996在 1996 年，新版本的 HTTP 对比之前的版本有了极大的改进，同时也被命名为 HTTP/1.0。与 HTTP/0.9 只能返回 HTML 不同的是，HTTP/1.0 支持处理多种返回的格式，比如图片、视频、文本或者其他格式的文件。它还增加了更多的请求方法（如 POST 和 HEAD），请求和响应的格式也相应做了改变，两者都增加了头信息；引入了状态码来定义返回的特征；引入了字符集支持；支持 多段类型 （ multi-part ） 、用户验证信息、缓存、内容编码格式等等。一个简单的 HTTP/1.0 请求大概是这样的：GET / HTTP/1.0 Host: kamranahmed.info User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) Accept: */* 正如你所看到的，在请求中附带了客户端中的一些个人信息、响应类型要求等内容。这些是在 HTTP/0.9 无法实现的，因为那时候没有头信息。一个对上述请求的响应例子如下所示：HTTP/1.0 200 OK Content-Type: text/plain Content-Length: 137582 Expires: Thu, 05 Dec 1997 16:00:00 GMT Last-Modified: Wed, 5 August 1996 15:55:28 GMT Server: Apache 0.84 (response body) (connection closed) 从 HTTP/1.0 （HTTP 后面跟的是版本号）早期开始，在状态码 200 之后就附带一个原因短语（你可以用来描述状态码）。在这个较新一点的版本中，请求和响应的头信息仍然必须是 ASCII 编码，但是响应的内容可以是任意类型，如图片、视频、HTML、文本或其他类型，服务器可以返回任意内容给客户端。所以这之后，HTTP 中的“ 超文本 （ Hyper Text ） ”成了名不副实。 HMTP （ 超媒体传输协议 （ Hypermedia transfer protocol ） ）可能会更有意义，但是我猜我们还是会一直沿用这个名字。HTTP/1.0 的一个主要缺点就是它不能在一个连接内拥有多个请求。这意味着，当客户端需要从服务器获取东西时，必须建立一个新的 TCP 连接，并且处理完单个请求后连接即被关闭。需要下一个东西时，你必须重新建立一个新的连接。这样的坏处在哪呢？假设你要访问一个有 10 张图片，5 个 样式表 （ stylesheet ） 和 5 个 JavaScript 的总计 20 个文件才能完整展示的一个页面。由于一个连接在处理完成一次请求后即被关闭，所以将有 20 个单独的连接，每一个文件都将通过各自对应的连接单独处理。当连接数量变得庞大的时候就会面临严重的性能问题，因为 TCP 启动需要经过三次握手，才能缓慢开始。三次握手三次握手是一个简单的模型，所有的 TCP 连接在传输应用数据之前都需要在三次握手中传输一系列数据包。SYN - 客户端选取一个随机数，我们称为 x，然后发送给服务器。SY…

PHP 、Python 等网站应用惊爆远程代理漏洞：httpoxy
type: item
date: 2016-07-20T05:26:00+08:00
description: 这是一个针对 PHP、Go、Python 等语言的 CGI 应用的漏洞。httpoxy 是一系列影响到以 CGI 或类 CGI 方式运行的应用的漏洞名称。简单的来说，它就是一个名字空间的冲突问题。RFC 3875 （CGI）中定义了从 HTTP 请求的 Proxy 头部直接填充到环境变量 HTTP_PROXY 的方式HTTP_PROXY 是一个常用于配置外发代理的环境变量这个缺陷会导致远程攻击。如果你正在运行着 PHP 或 CGI 程序，你应该马上封挡 Proxy 头部！马上！ 具体做法参见下面。httpoxy 是一个服务器端 web 应用漏洞，如果你没有在服务器端部署这些代码，则不用担心。如果我的 Web 应用存在这种漏洞会怎么样？当一个利用了此漏洞的 HTTP 客户端发起请求时，它可以做到：通过你的 Web 应用去代理请求别的 URL直接让你的服务器打开指定的远程地址及端口浪费服务器的资源，替攻击者访问指定的资源httpoxy 漏洞非常容易利用。希望安全人员尽快扫描该漏洞并快速修复。哪些受到影响？以下情况会存在安全漏洞：代码运行在 CGI 上下文中，这样 HTTP_PROXY 就会变成一个真实的或模拟的环境变量一个信任 HTTP_PROXY的 HTTP 客户端，并且支持代理功能该客户端会在请求内部发起一个 HTTP（或 HTTPS）请求下列情形是已经发现存在该缺陷的环境：语言环境HTTP 客户端PHPphp-fpm mod\_phpGuzzle 4+ ArtaxPythonwsgiref.handlers.CGIHandler twisted.web.twcgi.CGIScriptrequestsGonet/http/cginet/http肯定还有很多我们没有确定是否存在缺陷的语言和环境。PHP是否存在缺陷依赖于你的应用代码和 PHP 库，但是影响面看起来似乎非常广泛只要在处理用户请求的过程中使用了一个带有该缺陷的库，就可能被利用如果你使用了有该缺陷的库，该缺陷会影响任意 PHP 版本甚至会影响到替代的 PHP 运行环境，比如部署在 FastCGI 模式下的 HHVM确认影响 Guzzle、Artax 等库，可能还有很多很多的库也受影响Guzzle 4.0.0rc2 及其以后版本受影响，Guzzle 3 及更低版本不受影响其它的例子还有 Composer 的 StreamContextBuilder 工具类举个例子说，如果你在 Drupal 中使用 Guzzle 6 模块发起外发请求（比如请求一个天气 API），该模块发起的请求就存在这个 httpoxy 缺陷。PythonPython 代码只有部署在 CGI 模式下才存在缺陷，一般来说，存在缺陷的代码会使用类似 wsgiref.handlers.CGIHandler 的 CGI 控制器正常方式部署的 Python web 应用不受影响（大多数人使用 WSGI 或 FastCGI，这两个不受影响），所以受到影响的 Python 应用要比 PHP 少得多wsgi 不受影响，因为 os.environ 不会受到 CGI 数据污染存在缺陷的 requests 库必须信任和使用 os.environ['HTTP_PROXY']，并且不做内容检查GoGo 代码必须部署在 CGI 下才受影响。一般来说受到影响的代码会使用 net/http/cgi 包像 Python 一样，这并不是部署 Go 为一个 Web 应用的通常方式。所以受到影响的情形很少相较而言，Go 的 net/http/fcgi 包并不设置实际的环境变量，所以不受影响存在缺陷的 net/http 版本需要在外发请求中信任并使用 HTTP_PROXY ，并不做内容检查马上修复最好的修复方式是在他们攻击你的应用之前尽早封挡 Proxy 请求头部。这很简单，也很安全。说它安全是因为 IETF 没有定义 Proxy 请求头部，也没有列在 IANA 的消息头部注册中。这表明对该头部的使用是非标准的，甚至也不会临时用到符合标准的 HTTP 客户端和服务器绝不应该读取和发送这个头部你可以从请求中去掉这个头部或者干脆整个封挡使用它的请求你可以在上游没有发布补丁时自己来解决这个问题当 HTTP 请求进来时就检查它，这样可以一次性修复好许多存在缺陷的应用在反向代理和应用防火墙之后的应用剔除 Proxy 请求头部是安全的如何封挡 Proxy 请求头部依赖于你的配置。最容易的办法是在你的 Web 应用防火墙上封挡该头部，或者直接在 Apache 和 Nginx 上做也行。以下是一些如何做的指导：Nginx/FastCGI使用如下语句封挡传递给 PHP-FPM、PHP-PM 的请求头，这个语句可以放在 fastcgi.conf 或 fastcgi\…

451：对不起，从法律上说，它不存在
type: item
date: 2015-12-23T16:45:00+08:00
description: 上周五，IESG（ 互联网工程指导委员会 （ Internet Engineering Steering Group ） ）批准了一个新的互联网标准，为 HTTP 增加了一个新状态码：451 Unavailable For Legal Reasons。还需要一点点工作就会发布为正式的 RFC ，不过现在已经可以用了。缘起几年前，英国政府要求 ISP 们对海盗湾的内容进行封挡，Terence Eden 就这个事情写了一个帖子，建议应该有一个不同的状态码来区分禁止访问的原因。这样的话，ISP 们就可以向他们的用户说明为什么这些资源不能访问。有人提议使用数字 451 作为状态码，也有各种其它的建议。谷歌的 Tim Bray 受此启发，于前几年给 HTTP 工作组 HTTP Working Group 提交了一份提案，他（及很多人）认为应该将由于技术原因的不可见与非技术原因的不可见区分开来：403 状态码，用于描述由于技术原因禁止访问451 状态码，则用于描述由于国家法律所要求而禁止访问据说，451 这个数字来源于 Ray Bradbury 的一篇小说《 华氏 451 （ Fahrenheit 451 ） 》。发展最初，对于这份提案，IETF HTTP 工作组的主席 Mark Nottingham 是拒绝的。因为 HTTP 状态码是有限的，虽然说从 400 到 499 有足足一百个位置，但是谁也不知道将来会有什么需求。而当时也没有任何需要让程序/机器来区分禁止访问的这两种情形，所以不应该浪费代码——最多，在 HTTP 首部或页面上呈现具体原因就可以了。而 Tim 依旧坚持他的提案，并偶尔更新一下提案内容，和关心这件事的人谈论。有一些站点开始实验性的使用这个状态码，不过这并不足以让 IESG 同意增加新的状态码。但是，随着网络上的审查的越来越多，比如欧盟政府要求 ISP 禁止对盗版内容的访问，而韩国、俄罗斯和其它一些国家会限制某些内容的访问等等，IESG 意识到网站需要能够区分这其中的不同。此外，还有一些人希望能够自动找到和分类哪些内容是被审查的。这就需要一种机器可读的机制来区分 403 和 451 所代表的不同意义。451 能做什么和不能做什么虽然 451 状态码的原意是用于标示出哪些内容是被法律禁止访问的，比如可以用在网络设备上（比如防火墙）或 Web 服务器上。就目前已知的， Github、 Twitter、 Facebook 和 Google 都已经开始使用这个状态码来应对各个国家地区的审查要求了。但是显然，451 状态码并不能标示出所有的被审查的内容，也许有些国家（比如英国）的法律要求不允许使用这个状态码。本文内容编译自 Mark Nottingham 的博客、维基百科、Solidot 等来源。

Linux 命令行下嗅探 HTTP 流量的工具：httpry
type: item
date: 2014-11-03T02:04:00+08:00
description: 假设由于某种原因，你需要嗅探HTTP站点的流量（如HTTP请求与响应）。举个例子，你可能在测试一个web服务器的实验性功能，或者你在为某个web应用或RESTful服务排错，又或者你正在为PAC(proxy auto config)排错或寻找某个站点下载的恶意软件。不论什么原因，在这些情况下，进行HTTP流量嗅探对于系统管理、开发者、甚至最终用户来说都是很有帮助的。数据包嗅工具tcpdump被广泛用于实时数据包的导出，但是你需要设置过滤规则来捕获HTTP流量，甚至它的原始输出通常不能方便的停在HTTP协议层。实时web服务器日志解析器如ngxtop可以提供可读的实时web流量跟踪痕迹，但这仅适用于可完全访问live web服务器日志的情况。要是有一个仅用于抓取HTTP流量的类似tcpdump的数据包嗅探工具就非常好了。事实上，httpry就是:HTTP包嗅探工具。httpry捕获HTTP数据包，并且将HTTP协议层的数据内容以可读形式列举出来。通过这篇指文章，让我们了解如何使用httpry工具嗅探HTTP流量。在Linux上安装httpry基于Debian系统（Ubuntu 或 LinuxMint），基础仓库中没有httpry安装包(译者注：本人ubuntu14.04,仓库中已有包，可直接安装)。所以我们需要通过源码安装:$ sudo apt-get install gcc make git libpcap0.8-dev $ git clone https://github.com/jbittel/httpry.git $ cd httpry $ make $ sudo make install 在Fedora，CentOS 或 RHEL系统，可以使用如下yum命令安装httpry。在CentOS/RHEL系统上，运行yum之前使其能够访问EPEL repo。$ sudo yum install httpry 如果你仍想通过基于RPM系统的源码来安装httpry的话，你可以通过这几个步骤实现：$ sudo yum install gcc make git libpcap-devel $ git clone https://github.com/jbittel/httpry.git $ cd httpry $ make $ sudo make install httpry的基本用法以下是httpry的基本用法$ sudo httpry -i <network-interface> httpry就会监听指定的网络接口，并且实时的显示捕获到的HTTP请求/相应。在大多数情况下，由于发送与接到的数据包过多导致刷屏很快，难以分析。这时候你肯定想将捕获到的数据包保存下来以便离线分析。可以使用'b'或'-o'选项保存数据包。'-b'选项将数据包以二进制文件的形式保存下来，这样可以使用httpry软件打开文件以浏览。另一方面，'-o'选项将数据以可读的字符文件形式保存下来。以二进制形式保存文件：$ sudo httpry -i eth0 -b output.dump 浏览所保存的HTTP数据包文件：$ httpry -r output.dump 注意，不需要根用户权限就可以使用'-r'选项读取数据文件。将httpry数据以字符文件保存：$ sudo httpry -i eth0 -o output.txt httpry 的高级应用如果你想监视指定的HTTP方法（如：GET，POST，PUT，HEAD，CONNECT等），使用'-m'选项：$ sudo httpry -i eth0 -m get,head 如果你下载了httpry的源码，你会发现源码下有一些Perl脚本，这些脚本用于分析httpry输出。脚本位于目录httpry/scripts/plugins。如果你想写一个定制的httpry输出分析器，则这些脚可以作为很好的例子。其中一些有如下的功能：hostnames: 显示唯一主机名列表。find\_proxies: 探测web代理。search\_terms: 查找及统计在搜索服务里面的搜索词。content\_analysis: 查找含有指定关键的URL。xml\_output: 将输出转换为XML形式。log\_summary: 生成日志汇总。db\_dump: 将日志文件数据保存数据库。在使用这些脚本之前，首先使用'-o'选项运行httpry。当获取到输出文件后，立即使用如下命令执行脚本：$ cd httpry/scripts $ perl parse_log.pl -d ./plugins <httpry-output-file> 你可能在使用插件的时候遇到警告。比如，如果你没有安装带有DBI接口的MySQL数据库，那么使用db…