Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add proxy package and various fixes and cleanups #39

Merged
merged 3 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 13 additions & 46 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"log/slog"
"net"
"net/netip"
"os"
"path/filepath"
Expand Down Expand Up @@ -118,18 +117,12 @@ func runWarp(ctx context.Context, l *slog.Logger, bind netip.AddrPort, endpoint
}

tnet.StartProxy(bind)
l.Info("Serving proxy", "address", bind)
l.Info("serving proxy", "address", bind)

return nil
}

func runWarpWithPsiphon(ctx context.Context, l *slog.Logger, bind netip.AddrPort, endpoint string, country string) error {
// make a random bind address for warp
warpBindAddress, err := findFreePort("tcp")
if err != nil {
return err
}

conf, err := wiresocks.ParseConfig("./primary/wgcf-profile.ini", endpoint)
if err != nil {
return err
Expand All @@ -147,15 +140,18 @@ func runWarpWithPsiphon(ctx context.Context, l *slog.Logger, bind netip.AddrPort
return err
}

tnet.StartProxy(warpBindAddress)
warpBind, err := tnet.StartProxy(netip.MustParseAddrPort("127.0.0.1:0"))
if err != nil {
return err
}

// run psiphon
err = psiphon.RunPsiphon(ctx, l.With("subsystem", "psiphon"), warpBindAddress.String(), bind.String(), country)
err = psiphon.RunPsiphon(ctx, l.With("subsystem", "psiphon"), warpBind.String(), bind.String(), country)
if err != nil {
return fmt.Errorf("unable to run psiphon %w", err)
}

l.Info("Serving proxy", "address", bind)
l.Info("serving proxy", "address", bind)

return nil
}
Expand All @@ -179,20 +175,14 @@ func runWarpInWarp(ctx context.Context, l *slog.Logger, bind netip.AddrPort, end
return err
}

// Run virtual endpoint
virtualEndpointBindAddress, err := findFreePort("udp")
if err != nil {
return err
}

// Create a UDP port forward between localhost and the remote endpoint
err = wiresocks.NewVtunUDPForwarder(ctx, virtualEndpointBindAddress.String(), endpoints[1], tnet, singleMTU)
addr, err := wiresocks.NewVtunUDPForwarder(ctx, netip.MustParseAddrPort("127.0.0.1:0"), endpoints[1], tnet, singleMTU)
if err != nil {
return err
}

// Run inner warp
conf, err = wiresocks.ParseConfig("./secondary/wgcf-profile.ini", virtualEndpointBindAddress.String())
conf, err = wiresocks.ParseConfig("./secondary/wgcf-profile.ini", addr.String())
if err != nil {
return err
}
Expand All @@ -208,36 +198,13 @@ func runWarpInWarp(ctx context.Context, l *slog.Logger, bind netip.AddrPort, end
return err
}

tnet.StartProxy(bind)

l.Info("Serving proxy", "address", bind)
return nil
}

func findFreePort(network string) (netip.AddrPort, error) {
if network == "udp" {
addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
if err != nil {
return netip.AddrPort{}, err
}

conn, err := net.ListenUDP("udp", addr)
if err != nil {
return netip.AddrPort{}, err
}
defer conn.Close()

return netip.MustParseAddrPort(conn.LocalAddr().String()), nil
}
// Listen on TCP port 0, which tells the OS to pick a free port.
listener, err := net.Listen(network, "127.0.0.1:0")
_, err = tnet.StartProxy(bind)
if err != nil {
return netip.AddrPort{}, err // Return error if unable to listen on a port
return err
}
defer listener.Close() // Ensure the listener is closed when the function returns

// Get the port from the listener's address
return netip.MustParseAddrPort(listener.Addr().String()), nil
l.Info("serving proxy", "address", bind)
return nil
}

func createPrimaryAndSecondaryIdentities(l *slog.Logger, license string) error {
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ replace github.com/Psiphon-Labs/psiphon-tunnel-core => github.com/bepass-org/psi

require (
github.com/Psiphon-Labs/psiphon-tunnel-core v2.0.28+incompatible
github.com/bepass-org/proxy v0.0.0-20240201095508-c86216dd0aea
github.com/fatih/color v1.16.0
github.com/flynn/noise v1.1.0
github.com/frankban/quicktest v1.14.6
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/armon/go-proxyproto v0.0.0-20180202201750-5b7edb60ff5f h1:SaJ6yqg936TshyeFZqQE+N+9hYkIeL9AMr7S4voCl10=
github.com/armon/go-proxyproto v0.0.0-20180202201750-5b7edb60ff5f/go.mod h1:QmP9hvJ91BbJmGVGSbutW19IC0Q9phDCLGaomwTJbgU=
github.com/bepass-org/proxy v0.0.0-20240201095508-c86216dd0aea h1:6GKkjxDUxqq7uwA8U15N4PFURhdNN0OrxFuXc58MGUU=
github.com/bepass-org/proxy v0.0.0-20240201095508-c86216dd0aea/go.mod h1:RlF0oO3D6Ju6VYjtL1I6lVLdc3l8jA4ggleJc8S+P0Y=
github.com/bepass-org/psiphon-tunnel-core v0.0.0-20240311155012-9c2e10df08e5 h1:UVdsUQXhviRMzVA02BGzEHUYUBAAeSJYijqKWJvMCxs=
github.com/bepass-org/psiphon-tunnel-core v0.0.0-20240311155012-9c2e10df08e5/go.mod h1:vA5iCui7nfavWyBN8MsLYZ5xpKItjrTvPC0SuMWz48Q=
github.com/bifurcation/mint v0.0.0-20180306135233-198357931e61 h1:BU+NxuoaYPIvvp8NNkNlLr8aA0utGyuunf4Q3LJ0bh0=
Expand Down
67 changes: 67 additions & 0 deletions proxy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Table of Contents
- [Introduction](#introduction)
- [Features](#features)
- [Installation](#installation)
- [Examples](#examples)
- [Minimal](#minimal)
- [Customized](#customized)


## Introduction
The proxy module simplifies connection handling and offers a generic way to work with both HTTP and SOCKS connections,
making it a powerful tool for managing network traffic.


## Features
The Inbound Proxy project offers the following features:

- Full support for `HTTP`, `SOCKS5`, `SOCKS5h`, `SOCKS4` and `SOCKS4a` protocols.
- Handling of `HTTP` and `HTTPS-connect` proxy requests.
- Full support for both `IPv4` and `IPv6`.
- Able to handle both `TCP` and `UDP` traffic.

## Installation

```bash
go get github.com/bepass-org/proxy
```

### Examples

#### Minimal

```go
package main

import (
"github.com/bepass-org/proxy/pkg/mixed"
)

func main() {
proxy := mixed.NewProxy()
_ = proxy.ListenAndServe()
}
```

#### Customized

```go
package main

import (
"github.com/bepass-org/proxy/pkg/mixed"
)

func main() {
proxy := mixed.NewProxy(
mixed.WithBindAddress("0.0.0.0:8080"),
)
_ = proxy.ListenAndServe()
}

```

There are other examples provided in the [example](https://github.com/bepass-org/proxy/tree/main/example) directory



35 changes: 35 additions & 0 deletions proxy/example/customHandler/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package main

import (
"fmt"
"io"
"log"
"net"

"github.com/bepass-org/warp-plus/proxy/pkg/mixed"
"github.com/bepass-org/warp-plus/proxy/pkg/statute"
)

func main() {
proxy := mixed.NewProxy(
mixed.WithBindAddress("127.0.0.1:1080"),
mixed.WithUserHandler(generalHandler),
)
_ = proxy.ListenAndServe()
}

func generalHandler(req *statute.ProxyRequest) error {
fmt.Println("handling request to", req.Destination)
conn, err := net.Dial(req.Network, req.Destination)
if err != nil {
return err
}
go func() {
_, err := io.Copy(conn, req.Conn)
if err != nil {
log.Println(err)
}
}()
_, err = io.Copy(req.Conn, conn)
return err
}
10 changes: 10 additions & 0 deletions proxy/example/minimal/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

import (
"github.com/bepass-org/warp-plus/proxy/pkg/mixed"
)

func main() {
proxy := mixed.NewProxy()
_ = proxy.ListenAndServe()
}
69 changes: 69 additions & 0 deletions proxy/example/udpClient/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package main

import (
"encoding/binary"
"fmt"
"io"
"net"
"strconv"
)

func main() {
proxyAddr := "127.0.0.1:1080"
targetAddr := "<YOUR Netcat ip address>:4444"

// Connect to SOCKS5 proxy
conn, err := net.Dial("tcp", proxyAddr)
if err != nil {
panic(err)
}
defer conn.Close()

// Send greeting to SOCKS5 proxy
conn.Write([]byte{0x05, 0x01, 0x00})

// Read greeting response
response := make([]byte, 2)
io.ReadFull(conn, response)

// Send UDP ASSOCIATE request
conn.Write([]byte{0x05, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})

// Read UDP ASSOCIATE response
response = make([]byte, 10)
io.ReadFull(conn, response)

// Extract the bind address and port
bindIP := net.IP(response[4:8])
bindPort := binary.BigEndian.Uint16(response[8:10])

// Print the bind address
fmt.Printf("Bind address: %s:%d\n", bindIP, bindPort)

// Create UDP connection
udpConn, err := net.Dial("udp", fmt.Sprintf("%s:%d", bindIP, bindPort))
if err != nil {
panic(err)
}
defer udpConn.Close()

// Extract target IP and port
dstIP, dstPortStr, _ := net.SplitHostPort(targetAddr)
dstPort, _ := strconv.Atoi(dstPortStr)

// Construct the UDP packet with the target address and message
packet := make([]byte, 0)
packet = append(packet, 0x00, 0x00, 0x00) // RSV and FRAG
packet = append(packet, 0x01) // ATYP for IPv4
packet = append(packet, net.ParseIP(dstIP).To4()...)
packet = append(packet, byte(dstPort>>8), byte(dstPort&0xFF))
packet = append(packet, []byte("Hello, UDP through SOCKS5!")...)

// Send the UDP packet
udpConn.Write(packet)

// Read the response
buffer := make([]byte, 1024)
n, _ := udpConn.Read(buffer)
fmt.Println("Received:", string(buffer[10:n]))
}
Loading
Loading