Skip to content

Commit

Permalink
Initial Version
Browse files Browse the repository at this point in the history
  • Loading branch information
reneManqueros committed Jan 22, 2022
1 parent e0eb069 commit 31a2c9c
Show file tree
Hide file tree
Showing 8 changed files with 997 additions and 1 deletion.
45 changes: 44 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,44 @@
# socks-to-http
# SOCKS5 to HTTP proxy
#### Tool to convert a SOCKS5 proxy to HTTP

## Installation
Download:
```shell
git clone https://github.com/reneManqueros/socks-to-http
```

Compile:
```shell
cd socks-to-http && go build .
````

## Usage

Basic usage:
```shell
./sockstohttp run
```

## Parameters
Custom socks address - Default ":8081"
```shell
./sockstohttp run socks=127.0.0.1:8080
```

Custom listen address - Default ":8083":
```shell
./sockstohttp run listen=127.0.0.1:9090
```

Custom timeout (seconds) - Default "10":
```shell
./sockstohttp run timeout=20
```

Parameters can be combined:
```shell
./sockstohttp run timeout=20 listen=127.0.0.1:9090 socks=127.0.0.1:8080
```



19 changes: 19 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package cmd

import (
"fmt"
"github.com/spf13/cobra"
"os"
)

var rootCmd = &cobra.Command{
Use: "sockstohttp",
Short: "SOCKS to HTTP conversion proxy",
}

func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
50 changes: 50 additions & 0 deletions cmd/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package cmd

import (
"github.com/spf13/cobra"
"math/rand"
"sockstohttp/internal"
"strconv"
"strings"
"time"
)

var runCmd = &cobra.Command{
Use: "run",
Short: "Run socks to http proxy",
Run: func(cmd *cobra.Command, args []string) {

rand.Seed(time.Now().UnixMilli())

// Defaults
socksAddress := ":8081"
listenAddress := ":8083"
timeout := 10
// Overrides
for _, v := range args {
argumentParts := strings.Split(v, "=")
if len(argumentParts) == 2 {
if argumentParts[0] == "socks" {
socksAddress = argumentParts[1]
}
if argumentParts[0] == "listen" {
listenAddress = argumentParts[1]
}
if argumentParts[0] == "timeout" {
timeout, _ = strconv.Atoi(argumentParts[1])
}
}
}

internal.Server{
ListenAddress: listenAddress,
SOCKSAddress: socksAddress,
Timeout: timeout,
}.Run()
},
}

func init() {
rootCmd.AddCommand(runCmd)
runCmd.Flags()
}
13 changes: 13 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module sockstohttp

go 1.17

require (
github.com/spf13/cobra v1.3.0
golang.org/x/net v0.0.0-20220121175114-2ed6ce1e1725
)

require (
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)
762 changes: 762 additions & 0 deletions go.sum

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions internal/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package internal

import (
"io"
"net/http"
)

func copyHeader(dest, src http.Header) {
for k, vv := range src {
for _, v := range vv {
dest.Add(k, v)
}
}
}

func copyIO(dest io.WriteCloser, src io.ReadCloser) {
defer dest.Close()
defer src.Close()

_, _ = io.Copy(dest, src)
}
81 changes: 81 additions & 0 deletions internal/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package internal

import (
"context"
"golang.org/x/net/proxy"
"io"
"net"
"net/http"
"time"
)

const HTTP200 = "HTTP/1.1 200 Connection Established\r\n\r\n"
const CONNECT = "CONNECT"

type Server struct {
Dialer proxy.Dialer
ListenAddress string
SOCKSAddress string
Timeout int
}

// handleHTTP - Proxy HTTP requests
func (s *Server) handleHTTP(responseWriter http.ResponseWriter, request *http.Request) {
transport := http.Transport{
DialContext: s.Dialer.(interface {
DialContext(context context.Context, network, address string) (net.Conn, error)
}).DialContext,
}

response, err := transport.RoundTrip(request)
if err != nil {
return
}
defer response.Body.Close()
copyHeader(responseWriter.Header(), response.Header)
responseWriter.WriteHeader(response.StatusCode)
_, _ = io.Copy(responseWriter, response.Body)
}

//handleTunnel - Proxy CONNECT requests
func (s *Server) handleTunnel(responseWriter http.ResponseWriter, request *http.Request) {
hijacker, ok := responseWriter.(http.Hijacker)
if !ok {
return
}

sourceConnection, _, err := hijacker.Hijack()
if err != nil {
return
}

destinationConnection, err := s.Dialer.Dial("tcp", request.Host)
if err != nil {
_ = sourceConnection.Close()
return
}

_, _ = sourceConnection.Write([]byte(HTTP200))

go copyIO(sourceConnection, destinationConnection)
go copyIO(destinationConnection, sourceConnection)
}

//Run - Proxy all the things
func (s Server) Run() {
_ = http.ListenAndServe(s.ListenAddress, http.HandlerFunc(
func(responseWriter http.ResponseWriter, request *http.Request) {
d := &net.Dialer{
Timeout: time.Duration(s.Timeout) * time.Second,
}

s.Dialer, _ = proxy.SOCKS5("tcp", s.SOCKSAddress, nil, d)

if request.Method == CONNECT {
s.handleTunnel(responseWriter, request)
} else {
s.handleHTTP(responseWriter, request)
}
},
))
}
7 changes: 7 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

import "sockstohttp/cmd"

func main() {
cmd.Execute()
}

0 comments on commit 31a2c9c

Please sign in to comment.