Java 如何简单的诊断 https (SSL/TLS) 请求

如果你能控制整个 Java 应用的启动, 那么你可以很简单的加SSL/TLS 的 debug 参数去打印等多的信息. 比如:

java -Djavax.net.debug=all myApp
java -Djavax.net.debug=ss:plaintext myApp 

想查看更多可以用的参数: 必须找一个 App, 不能使用常见的 java -Djavax.net.debug=help -version

java -Djavax.net.debug=help myApp

一个访问百度首页的 (-Djavax.net.debug=ss:plaintext) 的输出:

javax.net.ssl|DEBUG|01|main|2021-08-06 07:43:20.943 PDT|SSLCipher.java:1769|Plaintext before ENCRYPTION (
  0000: 47 45 54 20 2F 20 48 54   54 50 2F 31 2E 30 0A 0A  GET / HTTP/1.0..
)
javax.net.ssl|DEBUG|01|main|2021-08-06 07:43:21.233 PDT|SSLCipher.java:1671|Plaintext after DECRYPTION (
  0000: 48 54 54 50 2F 31 2E 30   20 35 30 30 20 49 6E 74  HTTP/1.0 500 Int
  0010: 65 72 6E 61 6C 20 53 65   72 76 65 72 20 45 72 72  ernal Server Err
  0020: 6F 72 0D 0A 43 6F 6E 74   65 6E 74 2D 4C 65 6E 67  or..Content-Leng
  0030: 74 68 3A 20 30 0D 0A 43   6F 6E 74 65 6E 74 2D 54  th: 0..Content-T
  0040: 79 70 65 3A 20 74 65 78   74 2F 70 6C 61 69 6E 3B  ype: text/plain;
  0050: 20 63 68 61 72 73 65 74   3D 75 74 66 2D 38 0D 0A   charset=utf-8..
  0060: 44 61 74 65 3A 20 46 72   69 2C 20 30 36 20 41 75  Date: Fri, 06 Au
  0070: 67 20 32 30 32 31 20 31   34 3A 34 33 3A 32 31 20  g 2021 14:43:21 
  0080: 47 4D 54 0D 0A 53 65 72   76 65 72 3A 20 62 66 65  GMT..Server: bfe
  0090: 0D 0A 0D 0A                                        ....
)

更多信息参考:

  1. https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/ReadDebug.html
  2. https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#Debug
  3. https://access.redhat.com/solutions/973783

MAC 上解密 chrome 的 https 流量

Chrome 或者 Firefox 都支持: 如果设置了环境变量 SSLKEYLOGFILE, 就把 SSL/TLS 的 pre-master secret key 写到设置的文件里面去. 之后可以使用这个 pre-master secret key 文件在 wireshark 里面解密加密的流量.

  1. 设置 SSLKEYLOGFILE 环境变量
    可以简单在命令行使用 export 命令 (记得之后打开 Chrome 要在这个命令行)

    export SSLKEYLOGFILE=~/ssh_key.log
  2. 在同一个命令行窗口打开 chrome

    open /Applications/Google\ Chrome.app/
  3. 在 chrome 随便访问一个 https 的网站, 检查 ~/ssh_key.log 是不是有内容
  4. 打开 wireshark 拦截流量或者 使用 tcpdump 有针对性的拦截

    sudo tcpdump host 103.144.218.5 -w mydump.pcap 
  5. 打开 wireshark, 分析这个加密的流量.
    显示设置SSL/TLS 的 pre-master secret key log 文件:

菜单: preferences -> Protocols -> TLS (Wireshark 3.0 之前是 SSL):

Preferences.png

  1. 关于 key log 文件的格式:https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format

之后:

  1. 首先找到带有 data 的行
  2. 可以看 http 或 http 2 的数据
  3. 点击下面(3)的 Decrypted data, 其实里面看上去是乱码, 因为直接解密后还是压缩的, 所以是乱码;
  4. 点解下面(4)的 uncompressed entity body 可以看到加压后的明文
    xiaohui_pcap.png

算法学习笔记overview

  1. 数据机构: stack, queue, bag, union-find, priority queue
  2. 排序: quick sort, merge sort, heap sort, radix sort
  3. 查找: BST, red-black BST, Hash table
  4. 图算法: BSF, DSF, Prim, Kruskal, Dijkstra
  5. 字符串操作: KMP, regular expression, TST, Huffman, LZW
  6. 其它: B-Tree, Suffix Array, max-flow

为什么Java CMS GC 使用单线程做 Full GC?

虽然今天 CMS GC 已经不被推荐, 可是还经常被用来和G1 GC 做对比. 其中导致CMS 不被推荐的重要原因是: CMS 的full GC 是单线程的, 在如今多核统治天下的情况下, 单线程的 full GC 肯定比多线程的 full GC 慢很多.

CMS 什么情况下会产生full GC

  1. 并发模式失败(concurrent mode failures) 老年代并发回收的速度跟不上年轻代晋升的速度;
  2. 碎片化, 老年代虽然有足够的空间, 可是都是碎片化的, 没有一个连续的可容纳的空间;
  3. 元数据区(metaspace)/老年代没有空间;
  4. 明确的 System.gc() 或 Runtime.gc() 调用

为什么不把 parallel old 的算法引入CMS, 使之可以多线程

二者的数据结构不一样, 如果引入需要大量修改

为什么不重新为了 CMS 写一个多线程的 full gc?

据说开发工程师把更多的时间都用去写 G1 了, 并且 G1 各方面的期望都比CMS 好, 没有必要再写要给给CMS.

其它

google 内部有一个CMS 的老年代GC 实现, 并且曾经尝试patch到openJDK, 不过最后没有做到:
http://openjdk.java.net/jeps/8130200

最好还是用G1