Skip to content

Commit 8272d5b

Browse files
committed
serve http response for subdomain not found and client not online
1 parent f1f3ed4 commit 8272d5b

File tree

5 files changed

+59
-25
lines changed

5 files changed

+59
-25
lines changed

internal/client/config/config.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,6 @@ func (c *Config) SetDefaults() {
5858
for i := range c.Tunnels {
5959
c.Tunnels[i].setDefaults()
6060
}
61-
62-
c.Secure = true
63-
c.Debug = true
6461
}
6562

6663
type ClientConfig struct {

internal/client/ssh/ssh.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net"
1010
"os"
1111
"os/signal"
12+
"strings"
1213
"syscall"
1314
"time"
1415

@@ -72,7 +73,6 @@ func (s *SshClient) startListenerForClient() error {
7273
}
7374
defer sshClient.Close()
7475

75-
// remoteEndpoint := "localhost:0" // Remote address to listen on
7676
localEndpoint := s.config.Tunnel.GetAddr() // Local address to forward to
7777

7878
randomPorts := utils.GenerateRandomHttpPorts()[:1]
@@ -98,13 +98,15 @@ func (s *SshClient) startListenerForClient() error {
9898
remoteConn, err := s.listener.Accept()
9999
if err != nil {
100100
s.log.Error("failed to accept connection", "error", err)
101-
continue
101+
break
102102
}
103103

104104
// Connect to the local endpoint
105105
localConn, err := net.Dial("tcp", localEndpoint)
106106
if err != nil {
107-
s.log.Error("failed to connect to local endpoint", "error", err)
107+
// serve local html if the local server is not available
108+
// change this to beautiful template
109+
remoteConn.Write([]byte(strings.TrimSpace(utils.LocalServerNotOnline)))
108110
remoteConn.Close()
109111
continue
110112
}
@@ -113,6 +115,8 @@ func (s *SshClient) startListenerForClient() error {
113115
go tunnel(remoteConn, localConn)
114116
go tunnel(localConn, remoteConn)
115117
}
118+
119+
return nil
116120
}
117121

118122
func tunnel(src, dst net.Conn) {

internal/server/proxy/proxy.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"net/url"
1111
"os"
1212
"os/signal"
13+
"strings"
1314
"sync"
1415
"syscall"
1516
"time"
@@ -26,13 +27,19 @@ type Proxy struct {
2627
server *http.Server
2728
}
2829

30+
func (p *Proxy) GetServerAddr() string {
31+
return ":" + fmt.Sprint(p.config.Proxy.Port)
32+
}
33+
2934
func New(config *config.Config) *Proxy {
30-
return &Proxy{
35+
p := &Proxy{
3136
log: utils.GetLogger(),
3237
config: config,
3338
routes: make(map[string]string),
34-
server: &http.Server{Addr: ":" + fmt.Sprint(config.Proxy.Port)},
39+
server: nil,
3540
}
41+
p.server = &http.Server{Addr: p.GetServerAddr()}
42+
return p
3643
}
3744

3845
func (p *Proxy) GetRoute(src string) (string, error) {
@@ -77,7 +84,8 @@ func (p *Proxy) handleRequest(w http.ResponseWriter, r *http.Request) {
7784
subdomain := p.config.ExtractSubdomain(r.Host)
7885
target, err := p.GetRoute(subdomain)
7986
if err != nil {
80-
http.Error(w, err.Error(), http.StatusNotFound)
87+
w.WriteHeader(http.StatusNotFound)
88+
w.Write([]byte(strings.TrimSpace(utils.UnregisteredSubdomain)))
8189
return
8290
}
8391

@@ -90,7 +98,7 @@ func (p *Proxy) handleRequest(w http.ResponseWriter, r *http.Request) {
9098
}
9199

92100
func (p *Proxy) Start() {
93-
p.log.Info("starting proxy server", "host", p.config.Proxy.Host, "port", p.config.Proxy.Port)
101+
p.log.Info("starting proxy server", "port", p.GetServerAddr())
94102

95103
done := make(chan os.Signal, 1)
96104
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)

internal/server/ssh/sshd.go

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ func New(config *config.SshConfig, proxy *proxy.Proxy) *SshServer {
3232
}
3333
}
3434

35+
func (s *SshServer) GetServerAddr() string {
36+
return ":" + fmt.Sprint(s.config.Port)
37+
}
38+
3539
func (s *SshServer) getSshPublicKey() ssh.PublicKey {
3640
publicKey, err := os.ReadFile(s.config.KeysDir + "/id_rsa.pub")
3741
if err != nil {
@@ -41,13 +45,11 @@ func (s *SshServer) getSshPublicKey() ssh.PublicKey {
4145
return key
4246
}
4347

44-
type Status struct {
45-
user string
46-
status string
47-
}
48-
4948
func parseSshUsername(user string) (string, string) {
5049
output := strings.Split(user, ":")
50+
if len(output) != 2 {
51+
log.Fatal("invalid username format")
52+
}
5153
return output[0], output[1]
5254
}
5355

@@ -56,16 +58,8 @@ func (s *SshServer) Start() {
5658

5759
keyFromDisk := s.getSshPublicKey()
5860

59-
status := make(chan Status)
60-
61-
go func() {
62-
for st := range status {
63-
s.log.Info("connection status", "user", st.user, "status", st.status)
64-
}
65-
}()
66-
6761
server := ssh.Server{
68-
Addr: ":" + fmt.Sprint(s.config.Port),
62+
Addr: s.GetServerAddr(),
6963
Handler: ssh.Handler(func(sh ssh.Session) {
7064
select {}
7165
}),
@@ -85,6 +79,10 @@ func (s *SshServer) Start() {
8579
<-ctx.Done()
8680
// log user disconnection
8781
log.Printf("connection closed for %s", user)
82+
err := s.proxy.RemoveRoute(subdomain)
83+
if err != nil {
84+
s.log.Error("failed to remove route", "error", err)
85+
}
8886
}()
8987
return true
9088
}),
@@ -101,7 +99,7 @@ func (s *SshServer) Start() {
10199
done := make(chan os.Signal, 1)
102100
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
103101

104-
s.log.Info("starting SSH server", "host", s.config.Host, "port", s.config.Port)
102+
s.log.Info("starting SSH server", "port", s.GetServerAddr())
105103

106104
go func() {
107105
if err := server.ListenAndServe(); err != nil && !errors.Is(err, ssh.ErrServerClosed) {

internal/utils/http.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package utils
2+
3+
const LocalServerNotOnline = `
4+
HTTP/1.1 400 Bad Request
5+
Content-Type: text/html; charset=utf-8
6+
7+
<!DOCTYPE html>
8+
<html>
9+
<head>
10+
<title>Localport</title>
11+
</head>
12+
<body>
13+
<h1>Your local server is not online</h1>
14+
<h2>Try again after starting the server</h2>
15+
</body>
16+
</html>`
17+
18+
const UnregisteredSubdomain = `
19+
<!DOCTYPE html>
20+
<html>
21+
<head>
22+
<title>Localport</title>
23+
</head>
24+
<body>
25+
<h1>There is no tunnel running on this endpoint</h1>
26+
</body>
27+
</html>`

0 commit comments

Comments
 (0)