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

Client / Server #1

Closed
monok-o opened this issue Oct 19, 2021 · 1 comment
Closed

Client / Server #1

monok-o opened this issue Oct 19, 2021 · 1 comment

Comments

@monok-o
Copy link

monok-o commented Oct 19, 2021

Hey hey,
I don't really understand how to connect to a server with this library, I mean I don't understand what to do this "shadowsocks.PacketClient".
I'm trying to understand with the documentation but to be honest I'm a bit new with Go and also shadowsocks, it would be really nice if it's possible to give a little example.

What I'm trying to do looks like this:
UDP client -> shadowsocks client -> shadowsocks server -> UDP server

Sorry for bothering with this question.

Thank you!

@wzshiming
Copy link
Owner

I wrote an example of DNS proxy through ss client and server for your reference.

package main

import (
	"context"
	"log"
	"net"
	"os"
	"time"

	"github.com/wzshiming/shadowsocks"
	_ "github.com/wzshiming/shadowsocks/init"
)

func main() {
	ctx := context.Background()

	// Start remote server of Shadowsocks
	ssServer, err := shadowsocks.NewSimplePacketServer("ss://aes-128-cfb:123456@127.0.0.1:0")
	if err != nil {
		log.Println("NewSimplePacketServer", err)
		os.Exit(1)
	}

	// Print remote listening address
	ssServer.ProxyPacket = func(ctx context.Context, network, address string) (net.PacketConn, error) {
		pc, err := net.ListenPacket(network, address)
		if err != nil {
			return nil, err
		}
		log.Println("ss server to target address", pc.LocalAddr())
		return pc, nil
	}
	err = ssServer.Start(ctx)
	if err != nil {
		log.Println("Start", err)
		os.Exit(1)
	}

	// Create local client of Shadowsocks
	ssClient, err := shadowsocks.NewPacketClient(ssServer.ProxyURL())
	if err != nil {
		log.Println("NewPacketClient", err)
		os.Exit(1)
	}
	// Print local listening address
	ssClient.ProxyPacket = func(ctx context.Context, network, address string) (net.PacketConn, error) {
		pc, err := net.ListenPacket(network, address)
		if err != nil {
			return nil, err
		}
		log.Println("ss client to server", pc.LocalAddr())
		return pc, nil
	}

	// Create DNS client
	resolverClient := net.Resolver{
		PreferGo: true,
		Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
			// Use local client of Shadowsocks to connect to remote DNS server
			client, err := ssClient.ListenPacket(context.Background(), "udp", ":0")
			if err != nil {
				return nil, err
			}

			addr, err := net.ResolveUDPAddr("udp", address)
			if err != nil {
				return nil, err
			}

			return &wrap{PacketConn: client, remoteAddr: addr}, nil
		},
	}

	// Send DNS query
	for i := 0; i != 3; i++ {
		time.Sleep(1 * time.Second)
		addresses, err := resolverClient.LookupHost(ctx, "google.com")
		if err != nil {
			log.Println("LookupHost", err)
			os.Exit(1)
		}
		log.Println(addresses)
	}
}

type wrap struct {
	net.PacketConn
	remoteAddr net.Addr
}

func (t wrap) RemoteAddr() net.Addr {
	return t.remoteAddr
}

func (t *wrap) Write(b []byte) (n int, err error) {
	return t.PacketConn.WriteTo(b, t.remoteAddr)
}

func (t *wrap) Read(b []byte) (n int, err error) {
	n, addr, err := t.PacketConn.ReadFrom(b)
	if err != nil {
		return 0, err
	}
	if addr.String() == t.remoteAddr.String() {
		return n, nil
	}
	return t.Read(b)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants