Skip to content

Commit

Permalink
Merge pull request #7 from wadahiro/develop
Browse files Browse the repository at this point in the history
Add explicit proxy
  • Loading branch information
wadahiro authored Feb 4, 2018
2 parents f4cdb7f + 6f601e0 commit 95908fb
Show file tree
Hide file tree
Showing 11 changed files with 296 additions and 74 deletions.
8 changes: 7 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@
# version = "2.4.0"

required = ["github.com/cybozu-go/cmd"]

[[constraint]]
branch = "master"
name = "github.com/comail/colog"
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ Nothing needs to setup many tools. Nothing needs to configure iptables.
**go-transproxy** will start multiple proxy servers for these protocols.
Futheremore, it will configure iptables automatically.

**go-transproxy** also provides two types of explicit proxy(not transparent proxy).
One is a simple proxy delegating to upstream your proxy, another is for adding `Proxy-Authorization` header automatically.

## Requirement

**go-transproxy** supports only Linux iptables.
Expand Down Expand Up @@ -49,6 +52,10 @@ Options:
DNS Listen on TCP (default true)
-dns-udp
DNS Listen on UDP (default true)
-explicit-proxy-listen [host]:port
Explicit Proxy listen address for HTTP/HTTPS, as [host]:port Note: This proxy doesn't use authentication info of the `http_proxy` and `https_proxy` environment variables (default ":3132")
-explicit-proxy-with-auth-listen [host]:port
Explicit Proxy with auth listen address for HTTP/HTTPS, as [host]:port Note: This proxy uses authentication info of the `http_proxy` and `https_proxy` environment variables (default ":3133")
-http-proxy-listen [host]:port
HTTP Proxy listen address, as [host]:port (default ":3129")
-https-proxy-listen [host]:port
Expand Down
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/sh

VERSION=0.3
VERSION=0.4

DIR=$(cd $(dirname $0); pwd)
cd $DIR
Expand Down
81 changes: 57 additions & 24 deletions cmd/transproxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"flag"
"fmt"
"log"
"math/rand"
"net"
"os"
Expand All @@ -13,7 +14,7 @@ import (
"syscall"
"time"

log "github.com/Sirupsen/logrus"
"github.com/comail/colog"
transproxy "github.com/wadahiro/go-transproxy"
)

Expand Down Expand Up @@ -57,6 +58,14 @@ var (
"dns-proxy-listen", ":3131", "DNS Proxy listen address, as `[host]:port`",
)

explicitProxyListenAddress = fs.String(
"explicit-proxy-listen", ":3132", "Explicit Proxy listen address for HTTP/HTTPS, as `[host]:port` Note: This proxy doesn't use authentication info of the `http_proxy` and `https_proxy` environment variables",
)

explicitProxyWithAuthListenAddress = fs.String(
"explicit-proxy-with-auth-listen", ":3133", "Explicit Proxy with auth listen address for HTTP/HTTPS, as `[host]:port` Note: This proxy uses authentication info of the `http_proxy` and `https_proxy` environment variables",
)

dnsOverTCPDisabled = fs.Bool(
"dns-over-tcp-disabled", false, "Disable DNS-over-TCP for querying to public DNS")

Expand Down Expand Up @@ -85,16 +94,20 @@ func main() {
// seed the global random number generator, used in secureoperator
rand.Seed(time.Now().UTC().UnixNano())

level, err := log.ParseLevel(*loglevel)
// setup logger
colog.SetDefaultLevel(colog.LDebug)
colog.SetMinLevel(colog.LInfo)
level, err := colog.ParseLevel(*loglevel)
if err != nil {
log.Fatalf("Invalid log level: %s", err.Error())
log.Fatalf("alert: Invalid log level: %s", err.Error())
}
formatter := &log.TextFormatter{
FullTimestamp: true,
DisableColors: true,
}
log.SetFormatter(formatter)
log.SetLevel(level)
colog.SetMinLevel(level)
colog.SetFormatter(&colog.StdFormatter{
Colors: true,
Flag: log.Ldate | log.Ltime | log.Lmicroseconds,
})
colog.ParseFields(true)
colog.Register()

// handling no_proxy environment
noProxy := os.Getenv("no_proxy")
Expand All @@ -111,7 +124,7 @@ func main() {
},
)
if err := tcpProxy.Start(); err != nil {
log.Fatalf(err.Error())
log.Fatalf("alert: %s", err.Error())
}

dnsProxy := transproxy.NewDNSProxy(
Expand All @@ -133,11 +146,11 @@ func main() {
transproxy.HTTPProxyConfig{
ListenAddress: *httpProxyListenAddress,
NoProxy: np,
Verbose: level == log.DebugLevel,
Verbose: level == colog.LDebug,
},
)
if err := httpProxy.Start(); err != nil {
log.Fatalf(err.Error())
log.Fatalf("alert: %s", err.Error())
}

httpsProxy := transproxy.NewHTTPSProxy(
Expand All @@ -147,10 +160,30 @@ func main() {
},
)
if err := httpsProxy.Start(); err != nil {
log.Fatalf(err.Error())
log.Fatalf("alert: %s", err.Error())
}

explicitProxyWithAuth := transproxy.NewExplicitProxy(
transproxy.ExplicitProxyConfig{
ListenAddress: *explicitProxyWithAuthListenAddress,
UseProxyAuthorization: true,
},
)
if err := explicitProxyWithAuth.Start(); err != nil {
log.Fatalf("alert: %s", err.Error())
}

explicitProxy := transproxy.NewExplicitProxy(
transproxy.ExplicitProxyConfig{
ListenAddress: *explicitProxyListenAddress,
UseProxyAuthorization: false,
},
)
if err := explicitProxy.Start(); err != nil {
log.Fatalf("alert: %s", err.Error())
}

log.Infoln("All proxy servers started.")
log.Printf("info: All proxy servers started.")

dnsToPort := toPort(*dnsProxyListenAddress)
httpToPort := toPort(*httpProxyListenAddress)
Expand All @@ -172,12 +205,12 @@ func main() {
PublicDNS: outgoingPublicDNS,
})
if err != nil {
log.Fatalf("IPTables: %s", err.Error())
log.Printf("alert: %s", err.Error())
}

t.Start()

log.Infof(`IPTables: iptables rules inserted as follows.
log.Printf(`info: iptables rules inserted as follows.
---
%s
---`, t.Show())
Expand All @@ -187,17 +220,17 @@ func main() {
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
<-sig

log.Infoln("Proxy servers stopping.")
log.Printf("info: Proxy servers stopping.")

// start shutdown process
t.Stop()
log.Infoln("IPTables: iptables rules deleted.")
log.Printf("info: iptables rules deleted.")

if dnsProxy != nil {
dnsProxy.Stop()
}

log.Infoln("go-transproxy exited.")
log.Printf("info: go-transproxy exited.")
}

func useDNSProxy() bool {
Expand All @@ -210,16 +243,16 @@ func useDNSProxy() bool {
func toPort(addr string) int {
array := strings.Split(addr, ":")
if len(array) != 2 {
log.Fatalf("Invalid address, no port: %s", addr)
log.Printf("alert: Invalid address, no port: %s", addr)
}

i, err := strconv.Atoi(array[1])
if err != nil {
log.Fatalf("Invalid address, the port isn't number: %s", addr)
log.Printf("alert: Invalid address, the port isn't number: %s", addr)
}

if i > 65535 || i < 0 {
log.Fatalf("Invalid address, the port must be an integer value in the range 0-65535: %s", addr)
log.Printf("alert: Invalid address, the port must be an integer value in the range 0-65535: %s", addr)
}

return i
Expand All @@ -233,11 +266,11 @@ func toPorts(ports string) []int {
for _, v := range array {
i, err := strconv.Atoi(v)
if err != nil {
log.Fatalf("Invalid port, It's not number: %s", ports)
log.Printf("alert: Invalid port, It's not number: %s", ports)
}

if i > 65535 || i < 0 {
log.Fatalf("Invalid port, It must be an integer value in the range 0-65535: %s", ports)
log.Printf("alert: Invalid port, It must be an integer value in the range 0-65535: %s", ports)
}

p = append(p, i)
Expand Down
28 changes: 17 additions & 11 deletions common.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package transproxy
import (
"fmt"
"io"
"log"
"net"
"net/http"
"net/url"
"strings"
"sync"

log "github.com/Sirupsen/logrus"
"github.com/cybozu-go/netutil"
"github.com/cybozu-go/transocks"
)
Expand All @@ -28,7 +28,9 @@ func NewTCPListener(listenAddress string) (*TCPListener, error) {
if err != nil {
return nil, err
}
return &TCPListener{l}, nil
return &TCPListener{
Listener: l,
}, nil
}

func (l *TCPListener) Accept() (net.Conn, error) {
Expand All @@ -47,23 +49,27 @@ func (l *TCPListener) Accept() (net.Conn, error) {
return c, fmt.Errorf("GetOriginalDST failed - %s", err.Error())
}

log.Printf("debug: OriginalDST: %s", origAddr)
log.Printf("debug: LocalAddr: %s", tc.LocalAddr().String())
log.Printf("debug: RemoteAddr: %s", tc.RemoteAddr().String())

return &TCPConn{tc, origAddr.String()}, nil
}

func ListenTCP(listenAddress string, handler func(tc *TCPConn)) {
l, err := NewTCPListener(listenAddress)
if err != nil {
log.Fatalf("Error listening for tcp connections - %s", err.Error())
log.Fatalf("alert: Error listening for tcp connections - %s", err.Error())
}

for {
conn, err := l.Accept() // wait here
if err != nil {
log.Warnf("Error accepting new connection - %s", err.Error())
log.Printf("warn: Error accepting new connection - %s", err.Error())
return
}

log.Infoln("Accepted new connection")
log.Printf("debug: Accepted new connection")

go func(conn net.Conn) {
defer func() {
Expand All @@ -86,7 +92,7 @@ var pool = sync.Pool{
func Pipe(srcConn *TCPConn, destConn net.Conn) {
defer destConn.Close()

log.Debug("Start proxy")
log.Printf("debug: Start proxy")

wg := &sync.WaitGroup{}

Expand Down Expand Up @@ -124,7 +130,7 @@ func Pipe(srcConn *TCPConn, destConn net.Conn) {

wg.Wait()

log.Debug("End proxy")
log.Printf("debug: End proxy")
}

type NoProxy struct {
Expand All @@ -149,26 +155,26 @@ func useProxy(noProxy NoProxy, target string) bool {

for _, d := range noProxy.Domains {
if strings.HasSuffix(target, d) {
log.Infof("NO_PROXY: Matched no_proxy domain. Direct for %s", target)
log.Printf("debug: NO_PROXY: Matched no_proxy domain. Direct for %s", target)
return false
}
}

for _, ip := range noProxy.IPs {
if ip == target {
log.Infof("NO_PROXY: Matched no_proxy ip. Direct for %s", target)
log.Printf("debug: NO_PROXY: Matched no_proxy ip. Direct for %s", target)
return false
}
}

for _, cidr := range noProxy.CIDRs {
targetIP := net.ParseIP(target)
if cidr.Contains(targetIP) {
log.Infof("NO_PROXY: Matched no_proxy cidr. Direct for %s", target)
log.Printf("debug: NO_PROXY: Matched no_proxy cidr. Direct for %s", target)
return false
}
}

log.Infof("Use proxy for %s", target)
log.Printf("debug: Use proxy for %s", target)
return true
}
Loading

0 comments on commit 95908fb

Please sign in to comment.