mirror of
https://github.com/cbeuw/Cloak.git
synced 2024-11-09 19:10:44 +00:00
196 lines
14 KiB
Go
196 lines
14 KiB
Go
package server
|
|
|
|
import (
|
|
"crypto"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"github.com/cbeuw/Cloak/internal/ecdh"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestTouchStone(t *testing.T) {
|
|
pvBytes, _ := hex.DecodeString("10de5a3c4a4d04efafc3e06d1506363a72bd6d053baef123e6a9a79a0c04b547")
|
|
p, _ := ecdh.Unmarshal(pvBytes)
|
|
staticPv := p.(crypto.PrivateKey)
|
|
|
|
t.Run("correct time", func(t *testing.T) {
|
|
chBytes, _ := hex.DecodeString("1603010200010001fc0303ac530b5778469dbbc3f9a83c6ac35b63aa6a70c2014026ade30f2faf0266f0242068424f320bcad49b4315a761f9f6dec32b0a403c2d8c0ab337608a694c6e411c0024130113031302c02bc02fcca9cca8c02cc030c00ac009c013c01400330039002f0035000a0100018f00000011000f00000c7777772e62696e672e636f6d00170000ff01000100000a000e000c001d00170018001901000101000b00020100002300000010000e000c02683208687474702f312e310005000501000000000033006b0069001d00204655c2c83aaed1db2e89ed17d671fcdc76dc96e36bde8840022f1bda2f31019600170041543af1f8d28b37d984073f40e8361613da502f16e4039f00656f427de0f66480b2e77e3e552e126bb0cc097168f6e5454c7f9501126a2377fb40151f6cfc007e0e002b0009080304030303020301000d0018001604030503060308040805080604010501060102030201002d00020101001c00024001001500920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
|
|
ch, _ := parseClientHello(chBytes)
|
|
ai, err := unmarshalClientHello(ch, staticPv)
|
|
if err != nil {
|
|
t.Errorf("expecting no error, got %v", err)
|
|
return
|
|
}
|
|
|
|
nineSixSix := func() time.Time { return time.Unix(1565998966, 0) }
|
|
cinfo, err := touchStone(ai, nineSixSix)
|
|
if err != nil {
|
|
t.Errorf("expecting no error, got %v", err)
|
|
return
|
|
}
|
|
if cinfo.SessionId != 3710878841 {
|
|
t.Errorf("expecting session id 3710878841, got %v", cinfo.SessionId)
|
|
}
|
|
})
|
|
t.Run("roughly correct time", func(t *testing.T) {
|
|
chBytes, _ := hex.DecodeString("1603010200010001fc0303ac530b5778469dbbc3f9a83c6ac35b63aa6a70c2014026ade30f2faf0266f0242068424f320bcad49b4315a761f9f6dec32b0a403c2d8c0ab337608a694c6e411c0024130113031302c02bc02fcca9cca8c02cc030c00ac009c013c01400330039002f0035000a0100018f00000011000f00000c7777772e62696e672e636f6d00170000ff01000100000a000e000c001d00170018001901000101000b00020100002300000010000e000c02683208687474702f312e310005000501000000000033006b0069001d00204655c2c83aaed1db2e89ed17d671fcdc76dc96e36bde8840022f1bda2f31019600170041543af1f8d28b37d984073f40e8361613da502f16e4039f00656f427de0f66480b2e77e3e552e126bb0cc097168f6e5454c7f9501126a2377fb40151f6cfc007e0e002b0009080304030303020301000d0018001604030503060308040805080604010501060102030201002d00020101001c00024001001500920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
|
|
ch, _ := parseClientHello(chBytes)
|
|
ai, err := unmarshalClientHello(ch, staticPv)
|
|
if err != nil {
|
|
t.Errorf("expecting no error, got %v", err)
|
|
return
|
|
}
|
|
|
|
nineSixSixP50 := func() time.Time { return time.Unix(1565998966, 0).Add(50) }
|
|
_, err = touchStone(ai, nineSixSixP50)
|
|
if err != nil {
|
|
t.Errorf("expecting no error, got %v", err)
|
|
return
|
|
}
|
|
nineSixSixM50 := func() time.Time { return time.Unix(1565998966, 0).Truncate(50) }
|
|
_, err = touchStone(ai, nineSixSixM50)
|
|
if err != nil {
|
|
t.Errorf("expecting no error, got %v", err)
|
|
return
|
|
}
|
|
|
|
})
|
|
t.Run("over interval", func(t *testing.T) {
|
|
chBytes, _ := hex.DecodeString("1603010200010001fc0303ac530b5778469dbbc3f9a83c6ac35b63aa6a70c2014026ade30f2faf0266f0242068424f320bcad49b4315a761f9f6dec32b0a403c2d8c0ab337608a694c6e411c0024130113031302c02bc02fcca9cca8c02cc030c00ac009c013c01400330039002f0035000a0100018f00000011000f00000c7777772e62696e672e636f6d00170000ff01000100000a000e000c001d00170018001901000101000b00020100002300000010000e000c02683208687474702f312e310005000501000000000033006b0069001d00204655c2c83aaed1db2e89ed17d671fcdc76dc96e36bde8840022f1bda2f31019600170041543af1f8d28b37d984073f40e8361613da502f16e4039f00656f427de0f66480b2e77e3e552e126bb0cc097168f6e5454c7f9501126a2377fb40151f6cfc007e0e002b0009080304030303020301000d0018001604030503060308040805080604010501060102030201002d00020101001c00024001001500920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
|
|
ch, _ := parseClientHello(chBytes)
|
|
ai, err := unmarshalClientHello(ch, staticPv)
|
|
if err != nil {
|
|
t.Errorf("expecting no error, got %v", err)
|
|
return
|
|
}
|
|
|
|
nineSixSixOver := func() time.Time { return time.Unix(1565998966, 0).Add(TIMESTAMP_TOLERANCE + 10) }
|
|
_, err = touchStone(ai, nineSixSixOver)
|
|
if err == nil {
|
|
t.Errorf("expecting %v, got %v", ErrTimestampOutOfWindow, err)
|
|
return
|
|
}
|
|
})
|
|
t.Run("under interval", func(t *testing.T) {
|
|
chBytes, _ := hex.DecodeString("1603010200010001fc0303ac530b5778469dbbc3f9a83c6ac35b63aa6a70c2014026ade30f2faf0266f0242068424f320bcad49b4315a761f9f6dec32b0a403c2d8c0ab337608a694c6e411c0024130113031302c02bc02fcca9cca8c02cc030c00ac009c013c01400330039002f0035000a0100018f00000011000f00000c7777772e62696e672e636f6d00170000ff01000100000a000e000c001d00170018001901000101000b00020100002300000010000e000c02683208687474702f312e310005000501000000000033006b0069001d00204655c2c83aaed1db2e89ed17d671fcdc76dc96e36bde8840022f1bda2f31019600170041543af1f8d28b37d984073f40e8361613da502f16e4039f00656f427de0f66480b2e77e3e552e126bb0cc097168f6e5454c7f9501126a2377fb40151f6cfc007e0e002b0009080304030303020301000d0018001604030503060308040805080604010501060102030201002d00020101001c00024001001500920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
|
|
ch, _ := parseClientHello(chBytes)
|
|
ai, err := unmarshalClientHello(ch, staticPv)
|
|
if err != nil {
|
|
t.Errorf("expecting no error, got %v", err)
|
|
return
|
|
}
|
|
|
|
nineSixSixUnder := func() time.Time { return time.Unix(1565998966, 0).Add(TIMESTAMP_TOLERANCE - 10) }
|
|
_, err = touchStone(ai, nineSixSixUnder)
|
|
if err == nil {
|
|
t.Errorf("expecting %v, got %v", ErrTimestampOutOfWindow, err)
|
|
return
|
|
}
|
|
})
|
|
t.Run("not cloak psk", func(t *testing.T) {
|
|
chBytes, _ := hex.DecodeString("1603010246010002420303794ae79c6db7a31e67e2ce91b8afcb82995ae79ad1d0dc885f933e4193bf95cd208abd7a70f3b82cc31c02f1c2b94ba74d5222a66695a5cf92a366421d7f5eb9530022fafa130113021303c02bc02fc02cc030cca9cca8c013c014009c009d002f0035000a010001d75a5a00000000001e001c0000196c68332e676f6f676c6575736572636f6e74656e742e636f6d00170000ff01000100000a000a0008baba001d00170018000b00020100002300000010000e000c02683208687474702f312e31000500050100000000000d00140012040308040401050308050501080606010201001200000033002b0029baba000100001d002074bfe93336c364b43cf0879d997b2e11dc97068b86fc90174e0f2bcea1d4ed1c002d00020101002b000b0ababa0304030303020301001b00030200029a9a0001000029010500e000da00d1f6c0918f865390ae3ca33c77f61a1974cb4533456071b214ec018d17dc22845f2f72cf1dba48f9cdc0758803002dda9b964fad5522e82442af7cbbe242241e39233386f2383bce3ced8e16b1ae3f0ef52a706f58e1e6a1bca0cd3b3a2a4c4cb738770b01b56bf3e73c472bf4fb238cab510aa78f8427a3ca99f741aa433f548be460705f43a3abe878cec6ee3158c129406910b93e798e8a7aaffc2e7ff7b8fd872778d3687a0beaa1452fe7ec418070d537344b64d09f6edd053346ff9c9678eef6b8886882aba81d4be11d9df653de35659f93a22ac39399e3ba400021204e22b73261693967a9216fe4a3b004571c53f316309e76671a18d78931b5b072")
|
|
ch, _ := parseClientHello(chBytes)
|
|
ai, err := unmarshalClientHello(ch, staticPv)
|
|
if err != nil {
|
|
t.Errorf("expecting no error, got %v", err)
|
|
return
|
|
}
|
|
|
|
fiveOSix := func() time.Time { return time.Unix(1565999506, 0) }
|
|
cinfo, err := touchStone(ai, fiveOSix)
|
|
if err == nil {
|
|
t.Errorf("not a cloak, got nil error and cinfo %v", cinfo)
|
|
return
|
|
}
|
|
})
|
|
t.Run("not cloak no psk", func(t *testing.T) {
|
|
chBytes, _ := hex.DecodeString("1603010200010001fc0303eae4c204a867390a758fcff3afa5803cac3e07011cf0c9f3befc1267445aabee20fc398df698113617f8161cbcb89534efa892088a6c5e49246534e05f790ea36f00220a0a130113021303c02bc02fc02cc030cca9cca8c013c014009c009d002f0035000a010001910a0a000000000014001200000f63646e2e62697a69626c652e636f6d00170000ff01000100000a000a0008caca001d00170018000b00020100002300000010000e000c02683208687474702f312e31000500050100000000000d00140012040308040401050308050501080606010201001200000033002b0029caca000100001d00204c8f1563fb70c261bc0c32c1b568b8d02fab25f4094711e7868b1712751dc754002d00020101002b000b0a2a2a0304030303020301001b00030200026a6a000100001500c9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
|
|
ch, _ := parseClientHello(chBytes)
|
|
ai, err := unmarshalClientHello(ch, staticPv)
|
|
if err != nil {
|
|
t.Errorf("expecting no error, got %v", err)
|
|
return
|
|
}
|
|
|
|
sixOneFive := func() time.Time { return time.Unix(1565999615, 0) }
|
|
cinfo, err := touchStone(ai, sixOneFive)
|
|
if err == nil {
|
|
t.Errorf("not a cloak, got nil error and cinfo %v", cinfo)
|
|
return
|
|
}
|
|
})
|
|
|
|
}
|
|
|
|
func TestPrepareConnection(t *testing.T) {
|
|
nineSixSix := func() time.Time { return time.Unix(1565998966, 0) }
|
|
pvBytes, _ := hex.DecodeString("10de5a3c4a4d04efafc3e06d1506363a72bd6d053baef123e6a9a79a0c04b547")
|
|
p, _ := ecdh.Unmarshal(pvBytes)
|
|
|
|
getNewState := func() *State {
|
|
sta, _ := InitState(nineSixSix)
|
|
sta.staticPv = p.(crypto.PrivateKey)
|
|
sta.ProxyBook["shadowsocks"] = nil
|
|
return sta
|
|
}
|
|
|
|
t.Run("TLS correct", func(t *testing.T) {
|
|
sta := getNewState()
|
|
chBytes, _ := hex.DecodeString("1603010200010001fc0303ac530b5778469dbbc3f9a83c6ac35b63aa6a70c2014026ade30f2faf0266f0242068424f320bcad49b4315a761f9f6dec32b0a403c2d8c0ab337608a694c6e411c0024130113031302c02bc02fcca9cca8c02cc030c00ac009c013c01400330039002f0035000a0100018f00000011000f00000c7777772e62696e672e636f6d00170000ff01000100000a000e000c001d00170018001901000101000b00020100002300000010000e000c02683208687474702f312e310005000501000000000033006b0069001d00204655c2c83aaed1db2e89ed17d671fcdc76dc96e36bde8840022f1bda2f31019600170041543af1f8d28b37d984073f40e8361613da502f16e4039f00656f427de0f66480b2e77e3e552e126bb0cc097168f6e5454c7f9501126a2377fb40151f6cfc007e0e002b0009080304030303020301000d0018001604030503060308040805080604010501060102030201002d00020101001c00024001001500920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
|
|
info, _, err := PrepareConnection(chBytes, sta, nil)
|
|
if err != nil {
|
|
t.Errorf("failed to get client info: %v", err)
|
|
return
|
|
}
|
|
if info.SessionId != 3710878841 {
|
|
t.Error("failed to get correct session id")
|
|
return
|
|
}
|
|
if info.Transport.(fmt.Stringer).String() != "TLS" {
|
|
t.Errorf("wrong transport: %v", info.Transport)
|
|
return
|
|
}
|
|
})
|
|
t.Run("TLS correct but replay", func(t *testing.T) {
|
|
sta := getNewState()
|
|
chBytes, _ := hex.DecodeString("1603010200010001fc0303ac530b5778469dbbc3f9a83c6ac35b63aa6a70c2014026ade30f2faf0266f0242068424f320bcad49b4315a761f9f6dec32b0a403c2d8c0ab337608a694c6e411c0024130113031302c02bc02fcca9cca8c02cc030c00ac009c013c01400330039002f0035000a0100018f00000011000f00000c7777772e62696e672e636f6d00170000ff01000100000a000e000c001d00170018001901000101000b00020100002300000010000e000c02683208687474702f312e310005000501000000000033006b0069001d00204655c2c83aaed1db2e89ed17d671fcdc76dc96e36bde8840022f1bda2f31019600170041543af1f8d28b37d984073f40e8361613da502f16e4039f00656f427de0f66480b2e77e3e552e126bb0cc097168f6e5454c7f9501126a2377fb40151f6cfc007e0e002b0009080304030303020301000d0018001604030503060308040805080604010501060102030201002d00020101001c00024001001500920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
|
|
_, _, err := PrepareConnection(chBytes, sta, nil)
|
|
if err != nil {
|
|
t.Error("failed to prepare for the first time")
|
|
return
|
|
}
|
|
_, _, err = PrepareConnection(chBytes, sta, nil)
|
|
if err != ErrReplay {
|
|
t.Errorf("failed to return ErrReplay, got %v instead", err)
|
|
return
|
|
}
|
|
})
|
|
t.Run("Websocket correct", func(t *testing.T) {
|
|
sta, _ := InitState(func() time.Time { return time.Unix(1584358419, 0) })
|
|
sta.staticPv = p.(crypto.PrivateKey)
|
|
sta.ProxyBook["shadowsocks"] = nil
|
|
|
|
req := `GET / HTTP/1.1
|
|
Host: d2jkinvisak5y9.cloudfront.net:443
|
|
User-Agent: Go-http-client/1.1
|
|
Connection: Upgrade
|
|
Hidden: oJxeEwfDWg5k5Jbl8ttZD1sc0fHp8VjEtXHsqEoSrnaLRe/M+KGXkOzpc/2fRRg9Vk+wIWRsfv8IpoBPLbqO+ZfGsPXTjUJGiI9BqxrcJfkxncXA7FAHGpTc84tzBtZZ
|
|
Sec-WebSocket-Key: lJYh7X8DRXW1U0h9WKwVMA==
|
|
Sec-WebSocket-Version: 13
|
|
Upgrade: websocket
|
|
|
|
`
|
|
info, _, err := PrepareConnection([]byte(req), sta, nil)
|
|
if err != nil {
|
|
t.Errorf("failed to get client info: %v", err)
|
|
return
|
|
}
|
|
if info.Transport.(fmt.Stringer).String() != "WebSocket" {
|
|
t.Errorf("wrong transport: %v", info.Transport)
|
|
return
|
|
}
|
|
})
|
|
|
|
}
|