This commit is contained in:
世界 2022-04-15 15:04:45 +08:00
parent 04917323e6
commit 5991cfc072
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
13 changed files with 177 additions and 93 deletions

View file

@ -11,7 +11,6 @@ import (
"os"
"os/signal"
"runtime/debug"
"strconv"
"strings"
"syscall"
"time"
@ -31,7 +30,6 @@ import (
"github.com/sagernet/sing/protocol/shadowsocks/shadowaead"
"github.com/sagernet/sing/protocol/shadowsocks/shadowaead_2022"
"github.com/sagernet/sing/protocol/socks"
"github.com/sagernet/sing/protocol/wapd"
"github.com/sagernet/sing/transport/mixed"
"github.com/sagernet/sing/transport/system"
"github.com/sirupsen/logrus"
@ -54,7 +52,6 @@ type flags struct {
UseSystemRNG bool `json:"use_system_rng"`
ReducedSaltEntropy bool `json:"reduced_salt_entropy"`
ConfigFile string
WAPD bool
}
func main() {
@ -91,7 +88,6 @@ Only available with Linux kernel > 3.7.0.`)
command.Flags().BoolVarP(&f.Verbose, "verbose", "v", true, "Enable verbose mode.")
command.Flags().BoolVar(&f.UseSystemRNG, "use-system-rng", false, "Use system random number generator.")
command.Flags().BoolVar(&f.ReducedSaltEntropy, "reduced-salt-entropy", false, "Remapping salt to printable chars.")
command.Flags().BoolVar(&f.WAPD, "wapd", false, "Listen WADP server.")
err := command.Execute()
if err != nil {
@ -106,7 +102,6 @@ type LocalClient struct {
method shadowsocks.Method
dialer net.Dialer
bypass string
wapd *wapd.Listener
}
func NewLocalClient(f *flags) (*LocalClient, error) {
@ -252,10 +247,6 @@ func NewLocalClient(f *flags) (*LocalClient, error) {
client.Listener = mixed.NewListener(netip.AddrPortFrom(bind, f.LocalPort), nil, transproxyMode, client)
if f.WAPD {
client.wapd = wapd.NewListener(netip.MustParseAddr("255.255.255.255"), "http://127.0.0.1:"+strconv.Itoa(int(f.LocalPort))+"/proxy.pac", client)
}
if f.Bypass != "" {
err := geoip.LoadMMDB("Country.mmdb")
if err != nil {
@ -382,10 +373,6 @@ func Run(cmd *cobra.Command, flags *flags) {
logrus.Fatal(err)
}
if client.wapd != nil {
err = client.wapd.Start()
}
if err != nil {
logrus.Fatal(err)
}

View file

@ -43,6 +43,32 @@ func Filter[T any](arr []T, block func(it T) bool) []T {
return retArr
}
func Find[T any](arr []T, block func(it T) bool) T {
for _, it := range arr {
if block(it) {
return it
}
}
var defaultValue T
return defaultValue
}
func Uniq[T comparable](arr []T) []T {
result := make([]T, 0, len(arr))
seen := make(map[T]struct{}, len(arr))
for _, item := range arr {
if _, ok := seen[item]; ok {
continue
}
seen[item] = struct{}{}
result = append(result, item)
}
return result
}
func FilterIsInstance[T any, N any](arr []T, block func(it T) (N, bool)) []N {
var retArr []N
for _, it := range arr {
@ -67,7 +93,7 @@ func IsEmpty[T any](array []T) bool {
}
func IsNotEmpty[T any](array []T) bool {
return len(array) >= 0
return len(array) > 0
}
func IsBlank(str string) bool {
@ -96,6 +122,12 @@ func Must1(_ any, err error) {
}
}
func Must2(_ any, _ any, err error) {
if err != nil {
log.Fatalln(err)
}
}
func Close(closers ...any) error {
var retErr error
for _, closer := range closers {

View file

@ -74,6 +74,17 @@ func ParseAddrPort(address string, port string) (*AddrPort, error) {
return AddrPortFrom(ParseAddr(address), uint16(portInt)), nil
}
func AddrFromNetAddr(netAddr net.Addr) Addr {
switch addr := netAddr.(type) {
case *net.IPAddr:
return AddrFromIP(addr.IP)
case *net.IPNet:
return AddrFromIP(addr.IP)
default:
return nil
}
}
func AddrPortFromNetAddr(netAddr net.Addr) *AddrPort {
var ip net.IP
var port uint16

33
common/network/addr.go Normal file
View file

@ -0,0 +1,33 @@
package network
import (
"net"
"net/netip"
"github.com/sagernet/sing/common"
M "github.com/sagernet/sing/common/metadata"
)
func LocalAddrs() ([]netip.Addr, error) {
interfaceAddrs, err := net.InterfaceAddrs()
if err != nil {
return nil, err
}
return common.Map(common.Filter(common.Map(interfaceAddrs, func(addr net.Addr) M.Addr {
return M.AddrFromNetAddr(addr)
}), func(addr M.Addr) bool {
return addr != nil
}), func(it M.Addr) netip.Addr {
return it.Addr()
}), nil
}
func LocalPublicAddrs() ([]netip.Addr, error) {
publicAddrs, err := LocalAddrs()
if err != nil {
return nil, err
}
return common.Filter(publicAddrs, func(addr netip.Addr) bool {
return !(addr.IsPrivate() || addr.IsLoopback() || addr.IsMulticast() || addr.IsGlobalUnicast() || addr.IsLinkLocalUnicast() || addr.IsInterfaceLocalMulticast())
}), nil
}

32
common/network/http.go Normal file
View file

@ -0,0 +1,32 @@
package network
import (
"context"
"io/ioutil"
"net"
"net/http"
)
func HTTPClientWithNetwork(network string) *http.Client {
return &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, _, addr string) (net.Conn, error) {
var dialer net.Dialer
return dialer.DialContext(ctx, network, addr)
},
},
}
}
func GetContext(ctx context.Context, client *http.Client, url string) ([]byte, error) {
request, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return nil, err
}
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
return ioutil.ReadAll(response.Body)
}

23
common/network/pem.go Normal file
View file

@ -0,0 +1,23 @@
package network
import (
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
)
func PEMBlock(data interface{}) *pem.Block {
var pemBlock *pem.Block
switch key := data.(type) {
case *ecdsa.PrivateKey:
keyBytes, _ := x509.MarshalECPrivateKey(key)
pemBlock = &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes}
case *rsa.PrivateKey:
pemBlock = &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}
case *x509.CertificateRequest:
pemBlock = &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: key.Raw}
}
return pemBlock
}

32
common/os.go Normal file
View file

@ -0,0 +1,32 @@
package common
import (
"os"
"strings"
"github.com/v2fly/v2ray-core/v5/common"
)
func FileExists(path string) bool {
return common.Error2(os.Stat(path)) == nil
}
func WriteFile(path string, content []byte) error {
if strings.Contains(path, "/") {
parent := path[:strings.LastIndex(path, "/")]
if !FileExists(parent) {
err := os.MkdirAll(parent, 0o755)
if err != nil {
return err
}
}
}
file, err := os.Create(path)
if err != nil {
return err
}
defer file.Close()
_, err = file.Write(content)
return err
}

View file

@ -6,7 +6,7 @@ import (
"sort"
"strings"
"github.com/samber/lo"
"github.com/sagernet/sing/common"
)
// ErrInvalidDomain means insert domain is invalid
@ -89,7 +89,7 @@ func New(domains []string) (*DomainSet, error) {
}
sort.Strings(list)
list = lo.Uniq(list)
list = common.Uniq(list)
return &DomainSet{NewSet(list)}, nil
}

View file

@ -4,8 +4,8 @@ import (
"net"
"testing"
"github.com/sagernet/uot/common"
"github.com/sagernet/uot/common/buf"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
"golang.org/x/net/dns/dnsmessage"
)

6
go.mod
View file

@ -7,8 +7,6 @@ require (
github.com/klauspost/compress v1.15.1
github.com/openacid/low v0.1.21
github.com/oschwald/geoip2-golang v1.7.0
github.com/sagernet/uot v0.0.0-20220403125237-bf82029ad617
github.com/samber/lo v1.11.0
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.4.0
@ -30,11 +28,13 @@ require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/oschwald/maxminddb-golang v1.9.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)

13
go.sum
View file

@ -1,5 +1,6 @@
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -32,7 +33,10 @@ github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
@ -41,6 +45,7 @@ github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZ
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/openacid/errors v0.8.1/go.mod h1:GUQEJJOJE3W9skHm8E8Y4phdl2LLEN8iD7c5gcGgdx0=
github.com/openacid/low v0.1.21 h1:Tr2GNu4N/+rGRYdOsEHOE89cxUIaDViZbVmKz29uKGo=
github.com/openacid/low v0.1.21/go.mod h1:q+MsKI6Pz2xsCkzV4BLj7NR5M4EX0sGz5AqotpZDVh0=
@ -56,10 +61,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagernet/uot v0.0.0-20220403125237-bf82029ad617 h1:h46Ocvf7zWpatqOHcR4kw+k2GbGcMM7EzGjYG7wiGfM=
github.com/sagernet/uot v0.0.0-20220403125237-bf82029ad617/go.mod h1:T2LhXiIIvaoeKii21x1GONCee9u7N9Nnrqz5bY3SWsM=
github.com/samber/lo v1.11.0 h1:JfeYozXL1xfkhRUFOfH13ociyeiLSC/GRJjGKI668xM=
github.com/samber/lo v1.11.0/go.mod h1:2I7tgIv8Q1SG2xEIkRq0F2i2zgxVpnyPOP0d3Gj2r+A=
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c h1:pqy40B3MQWYrza7YZXOXgl0Nf0QGFqrOC0BKae1UNAA=
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
@ -78,7 +79,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
github.com/u-root/uio v0.0.0-20210528114334-82958018845c h1:BFvcl34IGnw8yvJi8hlqLFo9EshRInwWBs2M5fGWzQA=
github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
@ -91,8 +91,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 h1:iU7T1X1J6yxDr0rda54sWGkHgOp5XJrqm79gcNlC2VM=
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -134,6 +132,7 @@ google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscL
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -1,52 +0,0 @@
package wapd
import (
"fmt"
"net/netip"
"github.com/insomniacslk/dhcp/dhcpv4"
_ "github.com/insomniacslk/dhcp/dhcpv6"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
"github.com/sagernet/sing/transport/udp"
"github.com/sirupsen/logrus"
)
type Listener struct {
*udp.Listener
E.Handler
option dhcpv4.Option
}
func NewListener(bind netip.Addr, proxyURL string, errorHandler E.Handler) *Listener {
l := &Listener{
Handler: errorHandler,
option: dhcpv4.Option{
Code: OptionCode,
Value: dhcpv4.String(fmt.Sprint(proxyURL)),
},
}
l.Listener = udp.NewUDPListener(netip.AddrPortFrom(bind, dhcpv4.ServerPort), l)
return l
}
func (l *Listener) NewPacket(packet *buf.Buffer, metadata M.Metadata) error {
request, err := dhcpv4.FromBytes(packet.Bytes())
if err != nil {
return E.Cause(err, "bad dhcpv4 packet")
}
logrus.Trace("DHCPv4 request ", request)
if !request.IsOptionRequested(OptionCode) {
return nil
}
reply, err := dhcpv4.NewReplyFromRequest(request, dhcpv4.WithOption(l.option))
if err != nil {
return E.Cause(err, "create response")
}
_, err = l.WriteTo(reply.ToBytes(), metadata.Source.UDPAddr())
if err != nil {
return E.Cause(err, "write response")
}
return nil
}

View file

@ -1,13 +0,0 @@
package wapd
var OptionCode = optionCode{}
type optionCode struct{}
func (C optionCode) Code() uint8 {
return 252
}
func (C optionCode) String() string {
return "Web Proxy Auto-Discovery Protocol"
}