-
Notifications
You must be signed in to change notification settings - Fork 619
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TCP+SNI support arbitrary large Client Hello #423
Conversation
Use the TLS data to calculate the length of the Client Hello message so that arbitrary large messages are supported. Previoulsy messages larger than 1024 bytes failed due to a fixed size buffer. Note that a Client Hello message must still fit in one TLS record. The code for parsing the TLS data has been moved around a bit to ease unit testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I've punted on extracting the buffer size since why would the ClientHello ever be bigger than the 350 bytes of my test case? ;)
In general, this looks solid and I've added some comments on what to refactor. Thanks for taking this on.
proxy/tcp/sni_proxy.go
Outdated
return err | ||
} | ||
|
||
tlsData, err := createClientHelloBuffer(data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd prefer if this function would only determine the size of the buffer and not allocate it. Also, keep it in the tls_clienthello.go
since this is where the parsing logic for the TLS ClientHello header is. Also, I'd keep data
instead of tlsData
since there is no difference.
proxy/tcp/sni_proxy.go
Outdated
|
||
host, ok := readServerName(data) | ||
host, ok := readServerName(tlsData[5:]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment where the 5:
comes from (magic number).
proxy/tcp/sni_proxy_test.go
Outdated
{0x16, 0x03, 0x01, 0x01, 0xF4, 0x01, 0x00, 0x01, 0xf1}, | ||
} | ||
|
||
for i := 0; i < len(testCases); i++ { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like these test cases. Can you move them to the tls_clienthello_test.go
since they test the parsing.
When you refactor the method to just return the size of the buffer you can test for that as well. My suggestion is:
tests := []struct {
name string
data []byte
fail bool
len int
}{
{
name: "bad handshake length",
data: ...,
fail: true,
},
...
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
n, err := clientHelloBufferSize(tt.data)
if tt.fail && err == nil {
t.Fatal("should fail")
}
if got, want := n, tt.len; !tt.fail && got != want {
t.Fatalf("got buffer size %d want %d", got, want)
}
}
}
Also I
proxy/tcp/sni_proxy_test.go
Outdated
} | ||
} | ||
|
||
func TestCreateClientHelloBufferOk(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can then probably roll that test case into the previous table driven test.
proxy/tcp/tls_clienthello_test.go
Outdated
"github.com/fabiolb/fabio/assert" | ||
) | ||
|
||
func TestReadServerNameBadData(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you check whether you can also write a table driven test like the one I've outlined above?
Thanks for the review! I will have a look at it and get it fixed. |
All valid comments. Thanks for that! I hope that I got it right. I'm not used to the github flow so let me know if I should change something. |
Thanks! |
Use the TLS data to calculate the length of the Client Hello
message so that arbitrary large messages are supported. Previoulsy
messages larger than 1024 bytes failed due to a fixed size buffer.
Note that a Client Hello message must still fit in one TLS record.
The code for parsing the TLS data has been moved around
a bit to ease unit testing.
This is my first attempt using golang so please be aware of that! I don't think
that the performance impact should be significant. I may even improve the
memory footprint per connection since you often don't need as much as 1024 bytes for the
client hello.