Skip to content

Commit bb07847

Browse files
authored
Merge pull request #12 from kyochikuto/tls-fragment
Improve TLS Fragmentation
2 parents 6654baf + af2585d commit bb07847

4 files changed

Lines changed: 41 additions & 37 deletions

File tree

common/dialer/extended_tcp.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func (d *ExtendedTCPDialer) DialContext(ctx context.Context, network string, des
3030
// Create a TLS-Fragmented dialer
3131
if d.TLSFragment.Enabled {
3232
fragmentConn := &fragmentConn{
33-
dialer: &d.Dialer,
33+
dialer: d.Dialer,
3434
fragment: d.TLSFragment,
3535
network: network,
3636
destination: destination,

common/dialer/extended_tcp_stub.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func (d *ExtendedTCPDialer) DialContext(ctx context.Context, network string, des
2121
}
2222
// Create a TLS-Fragmented dialer
2323
fragmentConn := &fragmentConn{
24-
dialer: &d.Dialer,
24+
dialer: d.Dialer,
2525
fragment: d.TLSFragment,
2626
network: network,
2727
destination: destination,

common/dialer/fragment.go

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type TLSFragment struct {
2323
}
2424

2525
type fragmentConn struct {
26-
dialer *net.Dialer
26+
dialer net.Dialer
2727
fragment TLSFragment
2828
network string
2929
destination M.Socksaddr
@@ -50,41 +50,40 @@ func (c *fragmentConn) Write(b []byte) (n int, err error) {
5050
if c.conn == nil {
5151
return 0, c.err
5252
}
53-
// Check if payload is a valid TLS clientHello packet
54-
if len(b) >= 5 && b[0] == 22 {
55-
clientHelloLen := int(binary.BigEndian.Uint16(b[3:5]))
56-
clientHelloData := b[5:]
57-
58-
for i := 0; i < clientHelloLen; {
59-
fragmentEnd := i + int(randBetween(int64(c.fragment.SizeMin), int64(c.fragment.SizeMax)))
60-
if fragmentEnd > clientHelloLen {
61-
fragmentEnd = clientHelloLen
62-
}
63-
64-
fragment := clientHelloData[i:fragmentEnd]
65-
i = fragmentEnd
66-
67-
header := make([]byte, 5)
68-
header[0] = b[0]
69-
binary.BigEndian.PutUint16(header[1:], binary.BigEndian.Uint16(b[1:3]))
70-
binary.BigEndian.PutUint16(header[3:], uint16(len(fragment)))
71-
payload := append(header, fragment...)
72-
73-
_, err := c.conn.Write(payload)
74-
if err != nil {
75-
c.err = err
76-
return 0, c.err
77-
}
78-
79-
randomInterval := randBetween(int64(c.fragment.SleepMin), int64(c.fragment.SleepMax))
80-
time.Sleep(time.Duration(randomInterval))
53+
// Do not fragment if it's not a TLS clientHello packet
54+
if len(b) < 5 || b[0] != 22 {
55+
return c.conn.Write(b)
56+
}
57+
58+
clientHelloLen := int(binary.BigEndian.Uint16(b[3:5]))
59+
clientHelloData := b[5:]
60+
61+
for fragmentStart := 0; fragmentStart < clientHelloLen; {
62+
fragmentEnd := fragmentStart + int(randBetween(int64(c.fragment.SizeMin), int64(c.fragment.SizeMax)))
63+
if fragmentEnd > clientHelloLen {
64+
fragmentEnd = clientHelloLen
65+
}
66+
67+
header := make([]byte, 5)
68+
header[0] = b[0]
69+
binary.BigEndian.PutUint16(header[1:], binary.BigEndian.Uint16(b[1:3]))
70+
binary.BigEndian.PutUint16(header[3:], uint16(fragmentEnd-fragmentStart))
71+
payload := append(header, clientHelloData[fragmentStart:fragmentEnd]...)
72+
73+
_, err := c.conn.Write(payload)
74+
if err != nil {
75+
c.err = err
76+
return 0, c.err
77+
}
78+
79+
if c.fragment.SleepMax != 0 {
80+
time.Sleep(time.Duration(randBetween(int64(c.fragment.SleepMin), int64(c.fragment.SleepMax))) * time.Millisecond)
8181
}
8282

83-
return len(b), nil
83+
fragmentStart = fragmentEnd
8484
}
8585

86-
// Write directly if not a clientHello packet
87-
return c.conn.Write(b)
86+
return len(b), nil
8887
}
8988

9089
func (c *fragmentConn) Close() error {

option/fragment.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package option
22

33
import (
4+
"fmt"
45
"strconv"
56
"strings"
67

@@ -21,16 +22,20 @@ func ParseIntRange(str string) ([]uint64, error) {
2122
if len(splitString) == 2 {
2223
result[0], err = strconv.ParseUint(splitString[0], 10, 64)
2324
if err != nil {
24-
return nil, E.Cause(err, "Error parsing string to integer")
25+
return nil, E.Cause(err, "error parsing string to integer")
2526
}
2627
result[1], err = strconv.ParseUint(splitString[1], 10, 64)
2728
if err != nil {
28-
return nil, E.Cause(err, "Error parsing string to integer")
29+
return nil, E.Cause(err, "error parsing string to integer")
30+
}
31+
32+
if result[1] < result[0] {
33+
return nil, E.Cause(E.New(fmt.Sprintf("upper bound value (%d) must be greater than or equal to lower bound value (%d)", result[1], result[0])), "invalid range")
2934
}
3035
} else {
3136
result[0], err = strconv.ParseUint(splitString[0], 10, 64)
3237
if err != nil {
33-
return nil, E.Cause(err, "Error parsing string to integer")
38+
return nil, E.Cause(err, "error parsing string to integer")
3439
}
3540
result[1] = result[0]
3641
}

0 commit comments

Comments
 (0)