File: mock_sshserver.go

package info (click to toggle)
golang-github-containers-gvisor-tap-vsocks 0.8.1-3
  • links: PTS, VCS
  • area: main
  • in suites: experimental, forky, sid, trixie
  • size: 800 kB
  • sloc: sh: 95; makefile: 59
file content (130 lines) | stat: -rw-r--r-- 2,785 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// +build windows

package e2e

import (
	"bufio"
	"context"
	"fmt"
	"io"
	"net"
	"net/http"
	"strings"

	"github.com/sirupsen/logrus"
	"golang.org/x/crypto/ssh"
)

const fakeHostKey = `-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACAkXGLzDNnY5+xdAgnt8FlBIZtoFOZEdTUkNxkdSM05PgAAAJg9WMAvPVjA
LwAAAAtzc2gtZWQyNTUxOQAAACAkXGLzDNnY5+xdAgnt8FlBIZtoFOZEdTUkNxkdSM05Pg
AAAEAFvLprhpMPdNsxSwo1Cs5VP5joCh9XLicRqKE0JJzdxCRcYvMM2djn7F0CCe3wWUEh
m2gU5kR1NSQ3GR1IzTk+AAAAEmphc29uQFRyaXBlbC5sb2NhbAECAw==
-----END OPENSSH PRIVATE KEY-----`

type streamLocalDirect struct {
	SocketPath string
	Reserved0  string
	Reserved1  uint32
}

var cancel context.CancelFunc

func startMockServer() {
	sshConfig := &ssh.ServerConfig{
		NoClientAuth: true,
	}

	key, err := ssh.ParsePrivateKey([]byte(fakeHostKey))
	if err != nil {
		logrus.Errorf("Could not parse key: %s", err)
	}
	sshConfig.AddHostKey(key)

	listener, err := net.Listen("tcp", ":2134")
	if err != nil {
		panic(err)
	}

	var ctx context.Context
	ctx, cancel = context.WithCancel(context.Background())

	go func() {
	loop:
		for {
			select {
			case <-ctx.Done():
				break loop
			default:
				// proceed
			} 
			conn, err := listener.Accept()
			if err != nil {
				panic(err)
			}

			// From a standard TCP connection to an encrypted SSH connection
			_, chans, reqs, err := ssh.NewServerConn(conn, sshConfig)
			if err != nil {
				panic(err)
			}

			go handleRequests(reqs)
			// Accept all channels
			go handleChannels(chans)
		}
		listener.Close()
	}()
}

func stopMockServer() {
	cancel()
}

func handleRequests(reqs <-chan *ssh.Request) {
	for _ = range reqs {
	}
}

func handleChannels(chans <-chan ssh.NewChannel) {
	directMsg := streamLocalDirect{}
	for newChannel := range chans {
		if t := newChannel.ChannelType(); t != "direct-streamlocal@openssh.com" {
			newChannel.Reject(ssh.UnknownChannelType, fmt.Sprintf("unknown channel type: %s", t))
			continue
		}

		if err := ssh.Unmarshal(newChannel.ExtraData(), &directMsg); err != nil {
			logrus.Errorf("could not direct-streamlocal data: %s", err)

			newChannel.Reject(ssh.Prohibited, "invalid format")
			return
		}

		channel, _, err := newChannel.Accept()
		if err != nil {
			logrus.Errorf("could not accept channel: %s", err)
			continue
		}

		req, err := http.ReadRequest(bufio.NewReader(channel))
		if err != nil {
			logrus.Errorf("could not process http request: %s", err)
		}

		resp := http.Response{}
		resp.Close = true
		switch req.RequestURI {
		case "/ping":
			resp.StatusCode = 200
			resp.ContentLength = 4
			resp.Body = io.NopCloser(strings.NewReader("pong"))
		default:
			resp.StatusCode = 404
			resp.ContentLength = 0
		}
		resp.Write(channel)
		channel.CloseWrite()
	}
}