文件 uploads/downloads 的完整性是否由 TCP/HTTPS 保证?
Is the integrity of file uploads/downloads guaranteed by TCP/HTTPS?
假设我想将文件上传到网络服务器。甚至可能是一个相当大的文件(例如 30 MB)。它是通过典型的文件上传表单完成的(参见下面的最小示例)。
现在的网络还不是很完善。我看到这些类型的错误是可能的:
- 位翻转可能发生
- 包裹可能会丢失
- 包裹到达的顺序可能不是它们发送的顺序
- 一个包裹可以收到两次
正在阅读 TCP wiki article,我明白了
At the lower levels of the protocol stack, due to network congestion, traffic load balancing, or unpredictable network behaviour, IP packets may be lost, duplicated, or delivered out of order. TCP detects these problems, requests re-transmission of lost data, rearranges out-of-order data and even helps minimize network congestion to reduce the occurrence of the other problems. If the data still remains undelivered, the source is notified of this failure. Once the TCP receiver has reassembled the sequence of octets originally transmitted, it passes them to the receiving application. Thus, TCP abstracts the application's communication from the underlying networking details.
读到这里,我明白为什么下载的文件可能损坏的唯一原因是 (1) 下载后出现问题或 (2) 连接中断。
我错过了什么吗?为什么提供 Linux 图片的网站通常也提供 MD5 哈希值?文件 upload/download 通过 HTTPS(因此也通过 TCP)的完整性是否得到保证?
最小文件上传示例
HTML:
<!DOCTYPE html>
<html>
<head><title>Upload a file</title></head>
<body>
<form method="post" enctype="multipart/form-data">
<input name="file" type="file" />
<input type="submit"/>
</form>
</body>
</html>
Python/Flask:
"""
Prerequesites:
$ pip install flask
$ mkdir uploads
"""
import os
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config["UPLOAD_FOLDER"] = "uploads"
@app.route("/", methods=["GET", "POST"])
def upload_file():
if request.method == "POST":
# check if the post request has the file part
if "file" not in request.files:
flash("No file part")
return redirect(request.url)
file = request.files["file"]
# if user does not select file, browser also
# submit an empty part without filename
if file.filename == "":
flash("No selected file")
return redirect(request.url)
filename = secure_filename(file.filename)
file.save(os.path.join(app.config["UPLOAD_FOLDER"], filename))
return redirect(url_for("upload_file", filename=filename))
else:
return """<!DOCTYPE html>
<html>
<head><title>Upload a file</title></head>
<body>
<form method="post" enctype="multipart/form-data">
<input name="file" type="file" />
<input type="submit"/>
</form>
</body>
</html>"""
return "upload handled"
if __name__ == "__main__":
app.run()
Is the integrity of file uploads/downloads guaranteed by TCP/HTTPS?
简而言之:不。但是使用 HTTPS 比使用普通 TCP 更好。
TCP 的错误检测能力非常弱,因此它可能会检测到简单的位翻转并丢弃(并重新发送)损坏的数据包 - 但它不会检测到更复杂的错误。尽管 HTTPS 具有(通过 TLS 层)非常可靠的完整性保护,并且在传输过程中未检测到的数据损坏基本上是不可能的。
TCP 还具有强大的检测和防止重复和重新排序功能。 TLS(在 HTTPS 中)对这种数据损坏具有更强大的检测能力。
但是当 TCP 连接提前关闭时,例如服务器崩溃时,它会变得模糊。 TCP 本身没有消息指示,因此连接关闭通常用作消息结束指示符。例如,对于 FTP 数据连接是这样,但对于 HTTP(以及 HTTPS)也是如此。虽然 HTTP 通常有一个长度指示符(Content-length
header 或带有 Transfer-Encoding: chunked
的显式块大小),但它也将 TCP 连接的结束定义为消息的结束。如果在声明的消息结束之前到达连接结束,则客户端的行为会有所不同:一些会将数据视为已损坏,另一些会假定服务器已损坏(即错误的长度声明)并将连接关闭视为消息的有效结束。
理论上,TLS(在 HTTPS 中)有一个明确的 end-of-TLS 消息(TLS 关闭),这可能有助于检测早期连接关闭。在实践中,虽然实现可能只是关闭底层套接字 w/o 这一显式 TLS 关闭,但不幸的是,人们不能完全依赖它。
Why do sites that offer Linux images often also provide an MD5 hash?
还有一个失败点:下载可能在下载之前就已经损坏了。下载站点通常有多个镜像,在将文件发送到下载镜像时甚至在将文件发送到下载主机时都可能发生损坏。在下载的同时拥有一些强大的校验和有助于检测此类错误,只要校验和是在下载源创建的,因此是在数据损坏之前创建的。
假设我想将文件上传到网络服务器。甚至可能是一个相当大的文件(例如 30 MB)。它是通过典型的文件上传表单完成的(参见下面的最小示例)。
现在的网络还不是很完善。我看到这些类型的错误是可能的:
- 位翻转可能发生
- 包裹可能会丢失
- 包裹到达的顺序可能不是它们发送的顺序
- 一个包裹可以收到两次
正在阅读 TCP wiki article,我明白了
At the lower levels of the protocol stack, due to network congestion, traffic load balancing, or unpredictable network behaviour, IP packets may be lost, duplicated, or delivered out of order. TCP detects these problems, requests re-transmission of lost data, rearranges out-of-order data and even helps minimize network congestion to reduce the occurrence of the other problems. If the data still remains undelivered, the source is notified of this failure. Once the TCP receiver has reassembled the sequence of octets originally transmitted, it passes them to the receiving application. Thus, TCP abstracts the application's communication from the underlying networking details.
读到这里,我明白为什么下载的文件可能损坏的唯一原因是 (1) 下载后出现问题或 (2) 连接中断。
我错过了什么吗?为什么提供 Linux 图片的网站通常也提供 MD5 哈希值?文件 upload/download 通过 HTTPS(因此也通过 TCP)的完整性是否得到保证?
最小文件上传示例
HTML:
<!DOCTYPE html>
<html>
<head><title>Upload a file</title></head>
<body>
<form method="post" enctype="multipart/form-data">
<input name="file" type="file" />
<input type="submit"/>
</form>
</body>
</html>
Python/Flask:
"""
Prerequesites:
$ pip install flask
$ mkdir uploads
"""
import os
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config["UPLOAD_FOLDER"] = "uploads"
@app.route("/", methods=["GET", "POST"])
def upload_file():
if request.method == "POST":
# check if the post request has the file part
if "file" not in request.files:
flash("No file part")
return redirect(request.url)
file = request.files["file"]
# if user does not select file, browser also
# submit an empty part without filename
if file.filename == "":
flash("No selected file")
return redirect(request.url)
filename = secure_filename(file.filename)
file.save(os.path.join(app.config["UPLOAD_FOLDER"], filename))
return redirect(url_for("upload_file", filename=filename))
else:
return """<!DOCTYPE html>
<html>
<head><title>Upload a file</title></head>
<body>
<form method="post" enctype="multipart/form-data">
<input name="file" type="file" />
<input type="submit"/>
</form>
</body>
</html>"""
return "upload handled"
if __name__ == "__main__":
app.run()
Is the integrity of file uploads/downloads guaranteed by TCP/HTTPS?
简而言之:不。但是使用 HTTPS 比使用普通 TCP 更好。
TCP 的错误检测能力非常弱,因此它可能会检测到简单的位翻转并丢弃(并重新发送)损坏的数据包 - 但它不会检测到更复杂的错误。尽管 HTTPS 具有(通过 TLS 层)非常可靠的完整性保护,并且在传输过程中未检测到的数据损坏基本上是不可能的。
TCP 还具有强大的检测和防止重复和重新排序功能。 TLS(在 HTTPS 中)对这种数据损坏具有更强大的检测能力。
但是当 TCP 连接提前关闭时,例如服务器崩溃时,它会变得模糊。 TCP 本身没有消息指示,因此连接关闭通常用作消息结束指示符。例如,对于 FTP 数据连接是这样,但对于 HTTP(以及 HTTPS)也是如此。虽然 HTTP 通常有一个长度指示符(Content-length
header 或带有 Transfer-Encoding: chunked
的显式块大小),但它也将 TCP 连接的结束定义为消息的结束。如果在声明的消息结束之前到达连接结束,则客户端的行为会有所不同:一些会将数据视为已损坏,另一些会假定服务器已损坏(即错误的长度声明)并将连接关闭视为消息的有效结束。
理论上,TLS(在 HTTPS 中)有一个明确的 end-of-TLS 消息(TLS 关闭),这可能有助于检测早期连接关闭。在实践中,虽然实现可能只是关闭底层套接字 w/o 这一显式 TLS 关闭,但不幸的是,人们不能完全依赖它。
Why do sites that offer Linux images often also provide an MD5 hash?
还有一个失败点:下载可能在下载之前就已经损坏了。下载站点通常有多个镜像,在将文件发送到下载镜像时甚至在将文件发送到下载主机时都可能发生损坏。在下载的同时拥有一些强大的校验和有助于检测此类错误,只要校验和是在下载源创建的,因此是在数据损坏之前创建的。