leeweir / blog Goto Github PK
View Code? Open in Web Editor NEW通过issue写博客
Home Page: http://leeweir.github.io/
License: The Unlicense
通过issue写博客
Home Page: http://leeweir.github.io/
License: The Unlicense
证书链优化
一条完整的证书链包含根证书—中间证书—站点证书,TLS的身份认证是通过证书链完成的,浏览器从站点证书开始递归校验父证书,直至出现信任的根证书。完整的证书链大小在4K左右,证书是在TLS握手期间传送,由于TCP初始拥塞窗口的存在,如果证书太长可能会增加TCP连接发送数据的次数,产生额外的往返开销,在弱网环境下延迟会增加得很明显。配置证书链的最佳实践是只包含站点证书和中间证书,服务端只需要发送两个证书,证书链大小控制在3Kb以内,以减少TLS握手时证书传输时间。
False start
TLS False Start指客户端在发送Change Cipher Spec Finished 同时发送应用数据,服务端在 TLS 握手完成时直接返回应用数据。这样,应用数据的发送实际上并未等到握手全部完成。在启用False Start之后,TLS阶段只需要 一次RTT就可以开始传输应用数据,相当于客户端提前发送应用层数据,无需等待服务端的确认。在服务端满足NPN和forward secrecy的条件下,大部分浏览器都会默认启用。
优化后:
如下,在浏览器发送change cipher spec(315)之后,没有等待服务器的确认就立即发送了应用数据(316-319),相比没有启用的情况,可以优化50%的TLS握手时间
Todo:
在完成Tengine 升级到Nginx的改造后,启动Nginx对分布式Session Cache的支持,在Session Identifier的基础上 实现Session Cache的多机共享机制,提高Session Identifier命中率,提高简化握手的比率。
OCSP Stapling
OCSP Stapling是指服务端在证书链中包含颁发机构对证书的 OCSP 查询结果,从而让客户端的浏览器跳过本地发起验证的过程。服务端通常有更快的网络,获取 OCSP 响应更容易,也可以将 OCSP 响应缓存起来。OCSP 响应本身经过了数字签名,无法伪造,所以 OCSP Stapling 技术既提高了握手效率,也不会影响安全性。由客户端发起的OCSP验证大约需要500ms,而由服务器端开启验证+响应缓存后,可以在TLS握手阶段,将OCSP响应和证书链一起下发给客户端浏览器,节省客户端在线验证的开销。
Todo:
6月在生产环境开启OCSP Stapling
TLS Record Size
服务器在建立TLS连接时,会为每个连接分配Buffer,这个Buffer叫TLS Record Size。Size值如果过大, 单个Record在TCP层会被分成多个包发送,必须等待这些包全部送到后才能解密,一旦出现丢包、拥塞、重传,握手延时将相应增加。而过小的TLS Record Size降低用户响应延时却降低了网络吞吐和利用率,所以需要合理设置TLS Record Size的大小。
由于TLS Record Size要大于证书链和OCSP Stapling响应大小,证书链不会分成多个record;同时要小于初始拥塞窗口值,保证服务器在通信之初可以发送足够数据而不需要等待浏览器确认。
Nginx默认的ssl_buffer_size为16k。根据携程实际的证书链大小,目前调整为6K。
优化方向:
协议和加密算法选择,采用cloudflare推荐
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
复用ssl会话
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 180m;
添加hsts header
add_header Strict-Transport-Security max-age=15768000;
加强https安全性(可选项)
Google+:
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
Twitter:
strict-transport-security: max-age=631138519
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
PayPal:
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=14400
Facebook(配置了详细的CSP,关闭了XSS保护):
strict-transport-security: max-age=60
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 0
content-security-policy: default-src ;script-src https://.facebook.com http://.facebook.com https://.fbcdn.net http://.fbcdn.net .facebook.net .google-analytics.com .virtualearth.net .google.com 127.0.0.1: .spotilocal.com: chrome-extension://lifbcibllhkdhoafpjfnlhfpfgnpldfl 'unsafe-inline' 'unsafe-eval' https://.akamaihd.net http://.akamaihd.net;style-src * 'unsafe-inline';connect-src https://.facebook.com http://.facebook.com https://.fbcdn.net http://.fbcdn.net .facebook.net .spotilocal.com: https://.akamaihd.net ws://.facebook.com: http://.akamaihd.net https://fb.scanandcleanlocal.com:;
前不久一个新人问我如何在django的singal中实现post update,可是默认queryset的update是直接调用sql的,不会使用django orm中的save方法,signal中默认只有post save的方法。最后大致实现如下:
update() is converted directly to an SQL statement; it doesn't call save() on the model instances, and so the pre_save and post_save signals aren't emitted. If you want your signal receivers to be called, you should loop over the queryset, and for each model instance, make your changes and call save() yourself.
singals.py文件
-------------------自定义singal---------------
from django.dispatch import Signal
post_update = Signal(providing_args=["user"])
models.py文件
-----------對某个model,override其queryset中的update方法-----------
//引入自定义的signal文件
from tools import signals
class MyCustomQuerySet(models.query.QuerySet):
def update(self, **kwargs):
super(MyCustomQuerySet, self).update(**kwargs)
//update被调用时, 发送该singal
signals.post_update.send(sender=self.model, user="xxx")
print("finished!")
class MyCustomManager(models.Manager):
def get_queryset(self):
return MyCustomQuerySet(self.model, using=self._db)
class crontab_ping(models.Model):
name = models.CharField(max_length=64, blank=True, null=True)
objects = MyCustomManager()
callback.py文件:
-------接收signal,触发操作----------
from tools.signals import post_update
@receiver(post_update)
def post_update_callback(sender, **kwargs):
print(kwargs['user'])
print("post_update_success")
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.