Skip to content

Commit 9b292bb

Browse files
committed
preserve TLS ticket key and label reuse of old one
1 parent 471e6ed commit 9b292bb

2 files changed

Lines changed: 110 additions & 2 deletions

File tree

main.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ type CLIArgs struct {
314314
maxTLSVersion TLSVersionArg
315315
tlsALPNEnabled bool
316316
tlsSessionKeys [][32]byte
317+
tlsSameSessionKey bool
317318
bwLimit forward.LimitSpec
318319
bwBurst int64
319320
bwSeparate bool
@@ -505,6 +506,7 @@ func parse_args() *CLIArgs {
505506
args.tlsSessionKeys = append(args.tlsSessionKeys, [32]byte(key))
506507
return nil
507508
})
509+
flag.BoolVar(&args.tlsSameSessionKey, "tls-same-session-key", true, "issue new TLS session tickets with the same key used for previous ticket")
508510
flag.Func("config", "read configuration from file with space-separated keys and values", readConfig)
509511
flag.Parse()
510512
// pull up remaining parameters from other BW-related arguments
@@ -1006,7 +1008,7 @@ func run() int {
10061008
}
10071009

10081010
func makeServerTLSConfig(args *CLIArgs) (*tls.Config, error) {
1009-
cfg := tls.Config{
1011+
cfg := &tls.Config{
10101012
MinVersion: uint16(args.minTLSVersion),
10111013
MaxVersion: uint16(args.maxTLSVersion),
10121014
}
@@ -1043,8 +1045,11 @@ func makeServerTLSConfig(args *CLIArgs) (*tls.Config, error) {
10431045
}
10441046
if len(args.tlsSessionKeys) > 0 {
10451047
cfg.SetSessionTicketKeys(args.tlsSessionKeys)
1048+
if args.tlsSameSessionKey {
1049+
cfg = tlsutil.PreserveSessionKeys(cfg, args.tlsSessionKeys)
1050+
}
10461051
}
1047-
return &cfg, nil
1052+
return cfg, nil
10481053
}
10491054

10501055
func readConfig(filename string) error {

tlsutil/preserve.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package tlsutil
2+
3+
import (
4+
"crypto/tls"
5+
"errors"
6+
"net"
7+
)
8+
9+
type preservedKeyKey struct{}
10+
11+
type nonDefaultKeyUsedKey struct{}
12+
13+
func saveConnKey(conn ConnTagger, key [32]byte) {
14+
conn.SetTag(preservedKeyKey{}, key)
15+
}
16+
17+
func getConnKey(conn ConnTagger) ([32]byte, bool) {
18+
saved, ok := conn.GetTag(preservedKeyKey{})
19+
if !ok {
20+
return [32]byte{}, false
21+
}
22+
key, ok := saved.([32]byte)
23+
if !ok {
24+
return [32]byte{}, false
25+
}
26+
return key, true
27+
}
28+
29+
func setNonDefaultKeyUsed(conn ConnTagger, b bool) {
30+
conn.SetTag(nonDefaultKeyUsedKey{}, b)
31+
}
32+
33+
func WasNonDefaultKeyUsed(conn net.Conn) bool {
34+
tagger, ok := conn.(ConnTagger)
35+
if !ok {
36+
if netconner, ok := conn.(interface {
37+
NetConn() net.Conn
38+
}); ok {
39+
return WasNonDefaultKeyUsed(netconner.NetConn())
40+
}
41+
return false
42+
}
43+
saved, ok := tagger.GetTag(nonDefaultKeyUsedKey{})
44+
if !ok {
45+
return false
46+
}
47+
val, _ := saved.(bool)
48+
return val
49+
}
50+
51+
func PreserveSessionKeys(cfg *tls.Config, keys [][32]byte) *tls.Config {
52+
if len(keys) < 2 {
53+
// there's just one key defined, nothing to do
54+
return cfg
55+
}
56+
forkConfig := func(chi *tls.ClientHelloInfo) (*tls.Config, error) {
57+
return cfg.Clone(), nil
58+
}
59+
if cfg.GetConfigForClient != nil {
60+
forkConfig = cfg.GetConfigForClient
61+
}
62+
cfg = cfg.Clone()
63+
cfg.GetConfigForClient = func(chi *tls.ClientHelloInfo) (*tls.Config, error) {
64+
conn, ok := chi.Conn.(ConnTagger)
65+
if !ok {
66+
return nil, errors.New("tlsCfg.GetConfigForClient: connection does is not a ConnTagger")
67+
}
68+
cfg, err := forkConfig(chi)
69+
if err != nil {
70+
return nil, err
71+
}
72+
cfg.UnwrapSession = func(identity []byte, cs tls.ConnectionState) (*tls.SessionState, error) {
73+
skCfg := cfg.Clone()
74+
skCfg.SessionTicketKey = [32]byte{}
75+
for ki, key := range keys {
76+
skCfg.SetSessionTicketKeys([][32]byte{key})
77+
ss, err := skCfg.DecryptTicket(identity, cs)
78+
if err != nil {
79+
return nil, err
80+
}
81+
if ss != nil {
82+
// key match
83+
saveConnKey(conn, key)
84+
setNonDefaultKeyUsed(conn, ki > 0)
85+
return ss, nil
86+
}
87+
}
88+
return nil, nil
89+
}
90+
cfg.WrapSession = func(cs tls.ConnectionState, ss *tls.SessionState) ([]byte, error) {
91+
// is there previous key? if so, use it
92+
if key, ok := getConnKey(conn); ok {
93+
skCfg := cfg.Clone()
94+
skCfg.SessionTicketKey = [32]byte{}
95+
skCfg.SetSessionTicketKeys([][32]byte{key})
96+
return skCfg.EncryptTicket(cs, ss)
97+
}
98+
return cfg.EncryptTicket(cs, ss)
99+
}
100+
return cfg, nil
101+
}
102+
return cfg
103+
}

0 commit comments

Comments
 (0)