Skip to content

Commit

Permalink
Merge pull request #36 from blacknon/develop
Browse files Browse the repository at this point in the history
Version 0.1.12
  • Loading branch information
blacknon authored Jul 2, 2024
2 parents 5223f7b + 8bd7831 commit 60a6b62
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 30 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test_and_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ jobs:
- os: ubuntu-latest
runs-on: ${{ matrix.os }}
steps:
- name: Set up Go 1.17
- name: Set up Go 1.22
uses: actions/setup-go@v1
with:
go-version: 1.17
go-version: 1.22

- name: Check out code into the Go module directory
uses: actions/checkout@v1
Expand Down
8 changes: 4 additions & 4 deletions auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ package sshlib

import (
"fmt"
"io/ioutil"
"os"
"regexp"
"strings"

Expand Down Expand Up @@ -46,7 +46,7 @@ func CreateSignerPublicKey(key, password string) (signer ssh.Signer, err error)
key = getAbsPath(key)

// Read PrivateKey file
keyData, err := ioutil.ReadFile(key)
keyData, err := os.ReadFile(key)
if err != nil {
return
}
Expand Down Expand Up @@ -86,7 +86,7 @@ func CreateSignerPublicKeyPrompt(key, password string) (signer ssh.Signer, err e
key = getAbsPath(key)

// Read PrivateKey file
keyData, err := ioutil.ReadFile(key)
keyData, err := os.ReadFile(key)
if err != nil {
return
}
Expand Down Expand Up @@ -138,7 +138,7 @@ func CreateSignerCertificate(cert string, keySigner ssh.Signer) (certSigner ssh.
cert = getAbsPath(cert)

// Read Cert file
certData, err := ioutil.ReadFile(cert)
certData, err := os.ReadFile(cert)
if err != nil {
return
}
Expand Down
2 changes: 1 addition & 1 deletion connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ type Connect struct {
// Set it before CraeteClient.
ForwardX11Trusted bool

//
// Dynamic forward related logger
DynamicForwardLogger *log.Logger

// shell terminal log flag
Expand Down
76 changes: 58 additions & 18 deletions forward.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (

"github.com/armon/go-socks5"
xauth "github.com/blacknon/go-x11auth"
"github.com/elazarl/goproxy"
"golang.org/x/crypto/ssh"
)

Expand Down Expand Up @@ -158,8 +157,8 @@ func getX11DisplayNumber(display string) int {
//
// example) "127.0.0.1:22", "abc.com:9977"
func (c *Connect) TCPLocalForward(localAddr, remoteAddr string) (err error) {
// create listner
listner, err := net.Listen("tcp", localAddr)
// create listener
listener, err := net.Listen("tcp", localAddr)
if err != nil {
return
}
Expand All @@ -168,7 +167,7 @@ func (c *Connect) TCPLocalForward(localAddr, remoteAddr string) (err error) {
go func() {
for {
// local (type net.Conn)
local, err := listner.Accept()
local, err := listener.Accept()
if err != nil {
return
}
Expand All @@ -189,8 +188,8 @@ func (c *Connect) TCPLocalForward(localAddr, remoteAddr string) (err error) {
//
// example) "127.0.0.1:22", "abc.com:9977"
func (c *Connect) TCPRemoteForward(localAddr, remoteAddr string) (err error) {
// create listner
listner, err := c.Client.Listen("tcp", remoteAddr)
// create listener
listener, err := c.Client.Listen("tcp", remoteAddr)
if err != nil {
return
}
Expand All @@ -205,7 +204,7 @@ func (c *Connect) TCPRemoteForward(localAddr, remoteAddr string) (err error) {
}

// remote (type net.Conn)
remote, err := listner.Accept()
remote, err := listener.Accept()
if err != nil {
return
}
Expand Down Expand Up @@ -291,8 +290,8 @@ func (c *Connect) TCPReverseDynamicForward(address, port string) (err error) {
Logger: c.getDynamicForwardLogger(),
}

// create listner
listner, err := c.Client.Listen("tcp", net.JoinHostPort(address, port))
// create listener
listener, err := c.Client.Listen("tcp", net.JoinHostPort(address, port))
if err != nil {
return
}
Expand All @@ -304,25 +303,66 @@ func (c *Connect) TCPReverseDynamicForward(address, port string) (err error) {
}

// Listen
err = s.Serve(listner)
err = s.Serve(listener)
return
}

// HTTPDynamicForward forwarding http data.
// Like Dynamic forward (`ssh -D <port>`). but use http proxy.
func (c *Connect) HTTPDynamicForward(address, port string) (err error) {
// create http proxy. use goproxy
httpProxy := goproxy.NewProxyHttpServer()
// create dial
dial := c.Client.Dial

// set dial
httpProxy.ConnectDial = func(n, addr string) (net.Conn, error) {
return c.Client.Dial(n, addr)
// create listener
listener, err := net.Listen("tcp", net.JoinHostPort(address, port))
if err != nil {
return
}
defer listener.Close()

// create proxy server.
server := &http.Server{
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodConnect {
handleHTTPSProxy(dial, w, r)
} else {
handleHTTPProxy(dial, w, r)
}
}),
ErrorLog: c.getDynamicForwardLogger(),
}

// set logger
httpProxy.Logger = c.getDynamicForwardLogger()
// listen
err = server.Serve(listener)
return
}

// HTTPReverseDynamicForward reverse forwarding http data.
// Like Reverse Dynamic forward (`ssh -R <port>`). but use http proxy.
func (c *Connect) HTTPReverseDynamicForward(address, port string) (err error) {
// create dial
dial := net.Dial

// create listener
listener, err := c.Client.Listen("tcp", net.JoinHostPort(address, port))
if err != nil {
return
}
defer listener.Close()

// create proxy server.
server := &http.Server{
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodConnect {
handleHTTPSProxy(dial, w, r)
} else {
handleHTTPProxy(dial, w, r)
}
}),
ErrorLog: c.getDynamicForwardLogger(),
}

// listen
err = http.ListenAndServe(net.JoinHostPort(address, port), httpProxy)
err = server.Serve(listener)
return
}
6 changes: 1 addition & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ require (
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
golang.org/x/net v0.0.0-20220526153639-5463443f8c37
golang.org/x/sys v0.19.0
)

require (
github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5
golang.org/x/term v0.19.0
)

Expand All @@ -28,6 +24,6 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)

go 1.22.2
go 1.22.4

replace github.com/ThalesIgnite/crypto11 v1.2.5 => github.com/blacknon/crypto11 v1.2.6
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/elazarl/goproxy.v1 v1.0.0-20180725130230-947c36da3153 h1:i2sumy6EgvN2dbX7HPhoDc7hLyoym3OYdU5HlvUUrpE=
gopkg.in/elazarl/goproxy.v1 v1.0.0-20180725130230-947c36da3153/go.mod h1:xzjpkyedLMz3EXUTBbkRuuGPsxfsBX3Sy7J6kC9Gvoc=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
79 changes: 79 additions & 0 deletions http_proxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) 2024 Blacknon. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.

package sshlib

import (
"io"
"net"
"net/http"
"time"
)

// httpTransfer copies data between src and dst
func httpTransfer(dst io.WriteCloser, src io.ReadCloser) {
defer dst.Close()
defer src.Close()
io.Copy(dst, src)
}

// handleHTTPSProxy handles CONNECT method for HTTPS requests
func handleHTTPSProxy(dial func(network, addr string) (net.Conn, error), w http.ResponseWriter, r *http.Request) {
destConn, err := dial("tcp", r.Host)
if err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
}

// Write 200 OK response to the client
w.WriteHeader(http.StatusOK)

// Get underlying connection from ResponseWriter
clientConn, buf, err := w.(http.Hijacker).Hijack()
if err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
destConn.Close()
return
}

// Make sure to set read/write deadlines for both connections
clientConn.SetDeadline(time.Time{})
destConn.SetDeadline(time.Time{})

go httpTransfer(destConn, clientConn)
go httpTransfer(clientConn, destConn)

// Ensure any buffered data from the client is written to the destination
if buf.Reader.Buffered() > 0 {
io.Copy(destConn, buf)
}
}

// handleHTTPProxy handles HTTP requests
func handleHTTPProxy(dial func(network, addr string) (net.Conn, error), w http.ResponseWriter, r *http.Request) {
r.RequestURI = ""
r.URL.Scheme = "http"
if r.URL.Host == "" {
r.URL.Host = r.Host
}

transport := &http.Transport{
Dial: dial,
}

resp, err := transport.RoundTrip(r)
if err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
}
defer resp.Body.Close()

for key, value := range resp.Header {
for _, v := range value {
w.Header().Add(key, v)
}
}
w.WriteHeader(resp.StatusCode)
io.Copy(w, resp.Body)
}

0 comments on commit 60a6b62

Please sign in to comment.