@@ -26,7 +26,9 @@ type DomainGateway struct {
2626 DstAddr string // 10.0.0.1:3389
2727
2828 sshClient * gossh.Client
29+ jumpClient * gossh.Client
2930 SelectedGateway * model.Gateway
31+ Destination * model.Gateway
3032
3133 ln net.Listener
3234
@@ -40,10 +42,10 @@ func (d *DomainGateway) run() {
4042 if err != nil {
4143 break
4244 }
43- logger .Infof ("Accept new conn by gateway %s " , d .SelectedGateway . Name )
45+ logger .Infof ("Accept new conn by SSH forwarder %s " , d .Name () )
4446 go d .handlerConn (con )
4547 }
46- logger .Infof ("Stop proxy by gateway %s" , d .SelectedGateway . Name )
48+ logger .Infof ("Stop proxy by SSH forwarder %s" , d .Name () )
4749}
4850
4951func (d * DomainGateway ) handlerConn (srcCon net.Conn ) {
@@ -82,6 +84,16 @@ func (d *DomainGateway) GetListenAddr() *net.TCPAddr {
8284}
8385
8486func (d * DomainGateway ) getAvailableGateway () bool {
87+ if d .Destination != nil {
88+ sshClient , jumpClient , err := d .createDestinationSSHClient ()
89+ if err != nil {
90+ logger .Errorf ("Dial SSH destination %s err: %s" , d .Destination .Name , err )
91+ return false
92+ }
93+ d .sshClient = sshClient
94+ d .jumpClient = jumpClient
95+ return true
96+ }
8597 if d .SelectedGateway != nil {
8698 sshClient , err := d .createGatewaySSHClient (d .SelectedGateway )
8799 if err != nil {
@@ -94,7 +106,39 @@ func (d *DomainGateway) getAvailableGateway() bool {
94106 }
95107 return false
96108}
109+
110+ func (d * DomainGateway ) createDestinationSSHClient () (* gossh.Client , * gossh.Client , error ) {
111+ if d .SelectedGateway == nil {
112+ client , err := d .createGatewaySSHClient (d .Destination )
113+ return client , nil , err
114+ }
115+ jumpClient , err := d .createGatewaySSHClient (d .SelectedGateway )
116+ if err != nil {
117+ return nil , nil , err
118+ }
119+ addr := gatewaySSHAddress (d .Destination )
120+ conn , err := jumpClient .Dial ("tcp" , addr )
121+ if err != nil {
122+ _ = jumpClient .Close ()
123+ return nil , nil , err
124+ }
125+ _ = conn .SetDeadline (time .Now ().Add (miniTimeout ))
126+ clientConn , chans , reqs , err := gossh .NewClientConn (
127+ conn , addr , gatewaySSHConfig (d .Destination ),
128+ )
129+ if err != nil {
130+ _ = conn .Close ()
131+ _ = jumpClient .Close ()
132+ return nil , nil , err
133+ }
134+ _ = conn .SetDeadline (time.Time {})
135+ return gossh .NewClient (clientConn , chans , reqs ), jumpClient , nil
136+ }
97137func (d * DomainGateway ) createGatewaySSHClient (gateway * model.Gateway ) (* gossh.Client , error ) {
138+ return gossh .Dial ("tcp" , gatewaySSHAddress (gateway ), gatewaySSHConfig (gateway ))
139+ }
140+
141+ func gatewaySSHConfig (gateway * model.Gateway ) * gossh.ClientConfig {
98142 auths := make ([]gossh.AuthMethod , 0 , 3 )
99143 loginAccount := gateway .Account
100144 if loginAccount .IsSSHKey () {
@@ -110,26 +154,45 @@ func (d *DomainGateway) createGatewaySSHClient(gateway *model.Gateway) (*gossh.C
110154 return []string {loginAccount .Secret }, nil
111155 }))
112156 }
113- sshConfig := gossh.ClientConfig {
157+ return & gossh.ClientConfig {
114158 User : loginAccount .Username ,
115159 Auth : auths ,
116160 HostKeyCallback : NewTrustHostKeyCallback (),
117161 Config : createSSHConfig (),
118162 Timeout : miniTimeout ,
119163 HostKeyAlgorithms : allHostKeyAlgorithms (),
120164 }
165+ }
166+
167+ func gatewaySSHAddress (gateway * model.Gateway ) string {
121168 port := gateway .Protocols .GetProtocolPort ("ssh" )
122- addr := net .JoinHostPort (gateway .Address , strconv .Itoa (port ))
123- return gossh .Dial ("tcp" , addr , & sshConfig )
169+ return net .JoinHostPort (gateway .Address , strconv .Itoa (port ))
170+ }
171+
172+ func (d * DomainGateway ) Name () string {
173+ if d .Destination != nil {
174+ return d .Destination .Name
175+ }
176+ if d .SelectedGateway != nil {
177+ return d .SelectedGateway .Name
178+ }
179+ return "unknown"
124180}
125181func (d * DomainGateway ) Stop () {
126182 d .closeOnce ()
127183}
128184
129185func (d * DomainGateway ) closeOnce () {
130186 d .once .Do (func () {
131- _ = d .ln .Close ()
132- _ = d .sshClient .Close ()
187+ if d .ln != nil {
188+ _ = d .ln .Close ()
189+ }
190+ if d .sshClient != nil {
191+ _ = d .sshClient .Close ()
192+ }
193+ if d .jumpClient != nil {
194+ _ = d .jumpClient .Close ()
195+ }
133196 })
134197}
135198
0 commit comments