Skip to content

Commit 9f4730e

Browse files
committed
Added --echgrease command-line argument
1 parent 46844cb commit 9f4730e

File tree

6 files changed

+63
-25
lines changed

6 files changed

+63
-25
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ adheres to [Semantic Versioning][semver].
1111

1212
## [Unreleased]
1313

14+
### Added
15+
16+
* Added support for `--echgrease` command-line argument. This option is used to
17+
enable ECH Grease for TLS ClientHello.
18+
1419
[unreleased]: https://github.com/ameshkov/gocurl/compare/v1.4.6...HEAD
1520

1621
## [1.4.6] - 2025-03-21

README.md

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -262,39 +262,58 @@ Usage:
262262
gocurl [OPTIONS]
263263
264264
Application Options:
265-
--url=<URL> URL the request will be made to. Can be specified without any flags.
265+
--url=<URL> URL the request will be made to. Can be specified
266+
without any flags.
266267
-X, --request=<method> HTTP method. GET by default.
267-
-d, --data=<data> Sends the specified data to the HTTP server using content type application/x-www-form-urlencoded.
268-
-H, --header= Extra header to include in the request. Can be specified multiple times.
269-
-x, --proxy=[protocol://username:password@]host[:port] Use the specified proxy. The proxy string can be specified with a protocol:// prefix.
270-
--connect-to=<HOST1:PORT1:HOST2:PORT2> For a request to the given HOST1:PORT1 pair, connect to HOST2:PORT2 instead. Can be specified
271-
multiple times.
268+
-d, --data=<data> Sends the specified data to the HTTP server using
269+
content type application/x-www-form-urlencoded.
270+
-H, --header= Extra header to include in the request. Can be
271+
specified multiple times.
272+
-x, --proxy=[protocol://username:password@]host[:port] Use the specified proxy. The proxy string can be
273+
specified with a protocol:// prefix.
274+
--connect-to=<HOST1:PORT1:HOST2:PORT2> For a request to the given HOST1:PORT1 pair, connect
275+
to HOST2:PORT2 instead. Can be specified multiple
276+
times.
272277
-I, --head Fetch the headers only.
273278
-k, --insecure Disables TLS verification of the connection.
274279
--tlsv1.3 Forces gocurl to use TLS v1.3 or newer.
275280
--tlsv1.2 Forces gocurl to use TLS v1.2 or newer.
276-
--tls-max=<VERSION> (TLS) VERSION defines maximum supported TLS version. Can be 1.2 or 1.3. The minimum acceptable
277-
version is set by tlsv1.2 or tlsv1.3.
281+
--tls-max=<VERSION> (TLS) VERSION defines maximum supported TLS version.
282+
Can be 1.2 or 1.3. The minimum acceptable version is
283+
set by tlsv1.2 or tlsv1.3.
278284
--ciphers=<space-separated list of ciphers> Specifies which ciphers to use in the connection, see
279-
https://go.dev/src/crypto/tls/cipher_suites.go for the full list of available ciphers.
280-
--tls-servername=<HOSTNAME> Specifies the server name that will be sent in TLS ClientHello
285+
https://go.dev/src/crypto/tls/cipher_suites.go for the
286+
full list of available ciphers.
287+
--tls-servername=<HOSTNAME> Specifies the server name that will be sent in TLS
288+
ClientHello
281289
--http1.1 Forces gocurl to use HTTP v1.1.
282290
--http2 Forces gocurl to use HTTP v2.
283291
--http3 Forces gocurl to use HTTP v3.
284292
--ech Enables ECH support for the request.
285-
--echconfig=<base64-encoded data> ECH configuration to use for this request. Implicitly enables --ech when specified.
286-
-4, --ipv4 This option tells gocurl to use IPv4 addresses only when resolving host names.
287-
-6, --ipv6 This option tells gocurl to use IPv6 addresses only when resolving host names.
288-
--dns-servers=<DNSADDR1,DNSADDR2> DNS servers to use when making the request. Supports encrypted DNS: tls://, https://, quic://,
289-
sdns://
290-
--resolve=<[+]host:port:addr[,addr]...> Provide a custom address for a specific host. port is ignored by gocurl. '*' can be used instead of
291-
the host name. Can be specified multiple times.
292-
--tls-split-hello=<CHUNKSIZE:DELAY> An option that allows splitting TLS ClientHello in two parts in order to avoid common DPI systems
293-
detecting TLS. CHUNKSIZE is the size of the first bytes before ClientHello is split, DELAY is delay
294-
in milliseconds before sending the second part.
295-
--json-output Makes gocurl write machine-readable output in JSON format.
296-
-o, --output=<file> Defines where to write the received data. If not set, gocurl will write everything to stdout.
297-
--experiment=<name[:value]> Allows enabling experimental options. See the documentation for available options. Can be specified
293+
--echgrease Forces sending ECH grease in the ClientHello, but does
294+
not try to resolve the ECH configuration.
295+
--echconfig=<base64-encoded data> ECH configuration to use for this request. Implicitly
296+
enables --ech when specified.
297+
-4, --ipv4 This option tells gocurl to use IPv4 addresses only
298+
when resolving host names.
299+
-6, --ipv6 This option tells gocurl to use IPv6 addresses only
300+
when resolving host names.
301+
--dns-servers=<DNSADDR1,DNSADDR2> DNS servers to use when making the request. Supports
302+
encrypted DNS: tls://, https://, quic://, sdns://
303+
--resolve=<[+]host:port:addr[,addr]...> Provide a custom address for a specific host. port is
304+
ignored by gocurl. '*' can be used instead of the host
305+
name. Can be specified multiple times.
306+
--tls-split-hello=<CHUNKSIZE:DELAY> An option that allows splitting TLS ClientHello in two
307+
parts in order to avoid common DPI systems detecting
308+
TLS. CHUNKSIZE is the size of the first bytes before
309+
ClientHello is split, DELAY is delay in milliseconds
310+
before sending the second part.
311+
--json-output Makes gocurl write machine-readable output in JSON
312+
format.
313+
-o, --output=<file> Defines where to write the received data. If not set,
314+
gocurl will write everything to stdout.
315+
--experiment=<name[:value]> Allows enabling experimental options. See the
316+
documentation for available options. Can be specified
298317
multiple times.
299318
-v, --verbose Verbose output (optional).
300319

internal/client/cfcrypto/cfcrypto.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func Handshake(
8787
conf.NextProtos = []string{"http/1.1"}
8888
}
8989

90-
if cfg.ECH {
90+
if cfg.ECH || cfg.ECHGrease {
9191
conf.ECHEnabled = true
9292
}
9393

@@ -104,6 +104,9 @@ func Handshake(
104104
}
105105

106106
c := ctls.Client(conn, conf)
107+
108+
out.Debug("Starting TLS handshake")
109+
107110
err = c.Handshake()
108111

109112
if err != nil {

internal/client/clientdialer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func (d *clientDialer) DialTLSContext(_ context.Context, network, addr string) (
6666
}
6767

6868
_, postQuantum := d.cfg.Experiments[config.ExpPostQuantum]
69-
if d.cfg.ECH || postQuantum {
69+
if d.cfg.ECH || d.cfg.ECHGrease || postQuantum {
7070
d.conn, err = d.handshakeCTLS(conn)
7171
} else {
7272
d.conn, err = d.handshakeTLS(conn)

internal/config/config.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ type Config struct {
7272
// received from the DNS settings.
7373
ECH bool
7474

75+
// ECHGrease forces sending ECH grease in the ClientHello. This option
76+
// does not try to resolve the ECH configuration and is only used for
77+
// testing ECH grease.
78+
ECHGrease bool
79+
7580
// ECHConfigs is a set of ECH configurations that will be used when opening
7681
// an encrypted connection.
7782
ECHConfigs []ctls.ECHConfig
@@ -169,6 +174,7 @@ func ParseConfig() (cfg *Config, err error) {
169174
ForceHTTP2: opts.HTTPv2,
170175
ForceHTTP3: opts.HTTPv3,
171176
ECH: opts.ECH,
177+
ECHGrease: opts.ECHGrease,
172178
IPv4: opts.IPv4,
173179
IPv6: opts.IPv6,
174180
TLSServerName: opts.TLSServerName,

internal/config/options.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ type Options struct {
7070
// received from the DNS settings.
7171
ECH bool `long:"ech" description:"Enables ECH support for the request." optional:"yes" optional-value:"true"`
7272

73+
// ECHGrease forces sending ECH grease in the ClientHello. This option
74+
// does not try to resolve the ECH configuration and is only used for
75+
// testing ECH grease.
76+
ECHGrease bool `long:"echgrease" description:"Forces sending ECH grease in the ClientHello, but does not try to resolve the ECH configuration." optional:"yes" optional-value:"true"`
77+
7378
// ECHConfig is a custom ECH configuration to use for this request. If this
7479
// option is specified, there will be no attempt to discover the ECH
7580
// configuration using DNS.

0 commit comments

Comments
 (0)