Skip to content

Commit

Permalink
feat: support http(s)_proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
wweir committed Sep 9, 2024
1 parent c0f704a commit 3d6ee5e
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 7 deletions.
30 changes: 25 additions & 5 deletions cmd/sower/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@ var (
}

DNS struct {
Disable bool `default:"false" usage:"disable DNS proxy"`
Serve string `default:"127.0.0.1" required:"true" usage:"dns server ip"`
Serve6 string `usage:"dns server ipv6, eg: ::1"`
Fallback string `default:"223.5.5.5" required:"true" usage:"fallback dns server"`
Disable bool `default:"false" usage:"disable DNS proxy"`
Serve string `default:"127.0.0.1" required:"true" usage:"dns server ip"`
Serve6 string `usage:"dns server ipv6, eg: ::1"`
ServeIface string `usage:"use the IP in the net interface, if serve ip not setted. eg: eth0"`
Fallback string `default:"223.5.5.5" required:"true" usage:"fallback dns server"`
}
Socks5 struct {
Disable bool `default:"false" usage:"disable sock5 proxy"`
Expand Down Expand Up @@ -87,6 +88,25 @@ func init() {
Msg("Load config")
}

if conf.DNS.ServeIface != "" {
iface, err := net.InterfaceByName(conf.DNS.ServeIface)
log.DebugFatal(err).Str("iface", conf.DNS.ServeIface).Msg("get iface")
addrs, err := iface.Addrs()
log.InfoFatal(err).Str("iface", conf.DNS.ServeIface).Msg("get iface addrs")
for _, addr := range addrs {
ip, _, err := net.ParseCIDR(addr.String())
log.InfoFatal(err).Str("iface", conf.DNS.ServeIface).
Msg("parse iface addr: " + addr.String())

if ip.To4() != nil && conf.DNS.Serve == "" {
conf.DNS.Serve = ip.String()
}
if ip.To16() != nil && conf.DNS.Serve6 == "" {
conf.DNS.Serve = ip.String()
}
}
}

conf.Router.Direct.Rules = append(conf.Router.Direct.Rules,
conf.Remote.Addr, "**.in-addr.arpa", "**.ip6.arpa")
log.Info().
Expand All @@ -106,7 +126,6 @@ func main() {

if conf.DNS.Disable {
log.Info().Msg("DNS proxy disabled")

} else {
ips := make([]string, 0, 2)
if strings.TrimSpace(conf.DNS.Serve) != "" {
Expand Down Expand Up @@ -169,6 +188,7 @@ func loadRule(rule *suffixtree.Node, proxyDial router.ProxyDialFn, file, linePre
}
rule.GC()
}

func fetchRuleFile(proxyDial router.ProxyDialFn, file string) <-chan string {
if file == "" {
return make(chan string)
Expand Down
61 changes: 59 additions & 2 deletions cmd/sower/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,70 @@ func ServeSocks5(ln net.Listener, r *router.Router) {
go ServeSocks5(ln, r)
defer conn.Close()

addr, err := socks5.New().Unwrap(conn)
teeConn := teeconn.New(conn)

buf1 := make([]byte, 1)
if _, err := teeConn.Read(buf1); err != nil {
log.Warn().Err(err).
Msg("read socks5 version")
return
}

if buf1[0] != 5 {
teeConn.Reread()
serveHttpProxy(teeConn, r)
return
}

teeConn.Stop().Reread()
addr, err := socks5.New().Unwrap(teeConn)
if err != nil {
log.Warn().Err(err).
Msgf("parse socks5 target: %s", addr)
return
}

host, port := addr.(*socks5.AddrHead).Addr()
r.RouteHandle(conn, host, port)
r.RouteHandle(teeConn, host, port)
}

func serveHttpProxy(teeConn *teeconn.Conn, r *router.Router) {
req, err := http.ReadRequest(bufio.NewReader(teeConn))
if err != nil {
log.Warn().Err(err).
Msg("read http request")
return
}

teeConn.Stop()
switch req.Method {
case "CONNECT":
if _, err := teeConn.Write([]byte(req.Proto + " 200 Connection established\r\n\r\n")); err != nil {
log.Warn().Err(err).
Msg("write https proxy response")
return
}

host, port, err := router.ParseHostPort(req.Host, 443)
if err != nil {
log.Warn().Err(err).
Msg("parse https_proxy target")
return
}

rc, err := r.ProxyDial("tcp", host, port)
if err != nil {
log.Warn().Err(err).
Str("host", host).
Msg("dial proxy")
return
}
defer rc.Close()

relay.Relay(teeConn, rc)

default:
teeConn.Reread()
r.RouteHandle(teeConn, req.Host, 80)
}
}
22 changes: 22 additions & 0 deletions router/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package router

import (
"net"
"strconv"
)

func ParseHostPort(hostport string, defaultPort uint16) (string, uint16, error) {
host, port, err := net.SplitHostPort(hostport)
if err != nil {
return "", 0, err
}
if port == "" {
return host, defaultPort, nil
}

portInt, err := strconv.ParseUint(port, 10, 16)
if err != nil {
return "", 0, err
}
return host, uint16(portInt), nil
}

0 comments on commit 3d6ee5e

Please sign in to comment.