@@ -423,6 +423,11 @@ func (a *agent) handleSSHSession(session ssh.Session) (retErr error) {
423
423
if err != nil {
424
424
return err
425
425
}
426
+ // Set SSH connection environment variables, from the clients perspective.
427
+ srcAddr ,srcPort := addrToSSHEnvAddr (session .RemoteAddr ())
428
+ dstAddr ,dstPort := addrToSSHEnvAddr (session .LocalAddr ())
429
+ cmd .Env = append (cmd .Env ,fmt .Sprintf ("SSH_CLIENT=%s %s %s" ,srcAddr ,srcPort ,dstPort ))
430
+ cmd .Env = append (cmd .Env ,fmt .Sprintf ("SSH_CONNECTION=%s %s %s %s" ,srcAddr ,srcPort ,dstAddr ,dstPort ))
426
431
427
432
if ssh .AgentRequested (session ) {
428
433
l ,err := ssh .NewAgentListener ()
@@ -437,6 +442,8 @@ func (a *agent) handleSSHSession(session ssh.Session) (retErr error) {
437
442
sshPty ,windowSize ,isPty := session .Pty ()
438
443
if isPty {
439
444
cmd .Env = append (cmd .Env ,fmt .Sprintf ("TERM=%s" ,sshPty .Term ))
445
+
446
+ // The pty package sets `SSH_TTY` on supported platforms.
440
447
ptty ,process ,err := pty .Start (cmd )
441
448
if err != nil {
442
449
return xerrors .Errorf ("start command: %w" ,err )
@@ -691,6 +698,19 @@ func (a *agent) handleReconnectingPTY(ctx context.Context, rawID string, conn ne
691
698
}
692
699
}
693
700
701
+ // addrToSSHEnvAddr turns the address and port into space-separated values,
702
+ // works with IPv4, IPv6 and invalid addresses (such as [peer/unknown-addr]).
703
+ func addrToSSHEnvAddr (a net.Addr ) (addr string ,port string ) {
704
+ addr = a .String ()
705
+ port = "0"
706
+ li := strings .LastIndex (addr ,":" )
707
+ if li != - 1 {
708
+ port = addr [li + 1 :]
709
+ addr = addr [:li ]
710
+ }
711
+ return addr ,port
712
+ }
713
+
694
714
// dialResponse is written to datachannels with protocol "dial" by the agent as
695
715
// the first packet to signify whether the dial succeeded or failed.
696
716
type dialResponse struct {