@@ -24,6 +24,10 @@ import (
24
24
// getDefaultTransport.
25
25
var mTLSDialContext func () func (ctx context.Context , network , address string ) (net.Conn , error )
26
26
27
+ // localAddr is the local address to use when dialing an address. This address
28
+ // is defined by the environment variable STEP_CLIENT_ADDR.
29
+ var localAddr net.Addr
30
+
27
31
func init () {
28
32
// STEP_TLS_TUNNEL is an environment variable that can be set to do an TLS
29
33
// over (m)TLS tunnel to step-ca using identity-like credentials. The value
@@ -70,6 +74,29 @@ func init() {
70
74
}
71
75
}
72
76
}
77
+
78
+ // STEP_CLIENT_ADDR is an environment variable that can be set to define the
79
+ // local address to use when dialing an address. This can be useful when
80
+ // step is run behind a CIDR-based ACL.
81
+ //
82
+ // STEP_CLIENT_ADDR can be set to an IP ("127.0.0.1", "[::1]"), a hostname
83
+ // ("localhost"), or a host:port ("[::1]:0"). If the port is set to
84
+ // something other than ":0" and the dialer is created multiple times it
85
+ // will fail with an "address already in use" error.
86
+ //
87
+ // See https://github.com/smallstep/cli/issues/730
88
+ if v := os .Getenv ("STEP_CLIENT_ADDR" ); v != "" {
89
+ _ , _ , err := net .SplitHostPort (v )
90
+ if err != nil {
91
+ // assuming that the error is a missing port, if it's not it will
92
+ // panic below.
93
+ v += ":0"
94
+ }
95
+ localAddr , err = net .ResolveTCPAddr ("tcp" , v )
96
+ if err != nil {
97
+ panic (err )
98
+ }
99
+ }
73
100
}
74
101
75
102
// GetClientTLSConfig returns a tls.Config for client use configured with the
@@ -279,7 +306,8 @@ func getDefaultTLSConfig(sign *api.SignResponse) *tls.Config {
279
306
func getDefaultDialer () * net.Dialer {
280
307
// With the KeepAlive parameter set to 0, it will be use Golang's default.
281
308
return & net.Dialer {
282
- Timeout : 30 * time .Second ,
309
+ Timeout : 30 * time .Second ,
310
+ LocalAddr : localAddr ,
283
311
}
284
312
}
285
313
0 commit comments