add SOCKS mode (SOCKS4/4a/5)

SOCKS mode is similar to HTTP mode (#23) but does not depend on HTTP.

Supports SOCKS4 and SOCKS4a as well as SOCKS5 (because socat doesn't support SOCKS5).

The underlying library: https://pkg.go.dev/github.com/cybozu-go/usocksd@v1.1.0/socks

Example manifest:
```yaml
hostTemplate:
  http:
    listen: "127.0.0.1:18080"
  socks:
    listen: "127.0.0.1:18081"
  loopback:
    disable: true
  ports: ["80:127.0.0.1:80"]
```

This commit also adds changes for signal handling because required by the library.

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
Akihiro Suda
2020-10-28 17:59:22 +09:00
parent b057f55169
commit 285410625c
13 changed files with 227 additions and 16 deletions

View File

@@ -24,6 +24,7 @@ import (
"os/exec"
"os/signal"
"strings"
"syscall"
"time"
"github.com/davecgh/go-spew/spew"
@@ -59,6 +60,7 @@ var managerFlags = []cli.Flag{
var sigCh = make(chan os.Signal)
func managerAction(clicontext *cli.Context) error {
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
openEditor := clicontext.Bool("open-editor")
manifestPath := clicontext.Args().First()
if openEditor {
@@ -71,14 +73,18 @@ func managerAction(clicontext *cli.Context) error {
return errors.Errorf("no manifest file path was specified, run `%s show-example` to show an example, or run `%s --open-editor` to open an editor with an example file",
os.Args[0], os.Args[0])
}
return runManager(manifestPath)
err := runManager(manifestPath)
if err == errInterrupted {
logrus.Info("Interrupted. Exiting...")
err = nil
}
return err
}
func runManagerWithEditor() error {
if !isatty.IsTerminal(os.Stdout.Fd()) {
return errors.New("`--open-editor` requires stdout to be a terminal")
}
signal.Notify(sigCh, os.Interrupt)
editor := editorcmd.Detect()
if editor == "" {
return errors.New("could not detect a text editor binary, try setting $EDITOR")

1
go.mod
View File

@@ -3,6 +3,7 @@ module github.com/norouter/norouter
go 1.15
require (
github.com/cybozu-go/usocksd v1.1.0
github.com/davecgh/go-spew v1.1.1
github.com/elazarl/goproxy v0.0.0-20201021153353-00ad82a08272
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510

35
go.sum
View File

@@ -12,6 +12,7 @@ cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Microsoft/go-winio v0.4.15-0.20200908182639-5b44b70ab3ab/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
@@ -37,6 +38,14 @@ github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cybozu-go/log v1.5.0 h1:cjLr+pNga4NL5sj5vnnG00xKmKXSWx0grQQ4LnV1Ris=
github.com/cybozu-go/log v1.5.0/go.mod h1:zpfovuCgUx+a/ErvQrThoT+/z1RVQoLDOf95wkBeRiw=
github.com/cybozu-go/netutil v1.2.0 h1:UBO0+hB43zd5mIXRfD195eBMHvgWlHP2mYuQ2F5Yxtg=
github.com/cybozu-go/netutil v1.2.0/go.mod h1:Wx92iF1dPrtuSzLUMEidtrKTFiDWpLcsYvbQ1lHSmxY=
github.com/cybozu-go/usocksd v1.1.0 h1:0g0MbyhOFWaR0Iv3Kc+6YnlWeNXWRj3Wh67cdmvG3dk=
github.com/cybozu-go/usocksd v1.1.0/go.mod h1:9nuohcMvU4K2oNIcyJG5ysaNdXJ8ZCQmDAaWvrO0WcU=
github.com/cybozu-go/well v1.8.1 h1:YlEPreiDBI+KxE5rcAkkaB5j/Iyow6nIVmUpq3u5DYQ=
github.com/cybozu-go/well v1.8.1/go.mod h1:9PK1AltjltFwZBtTWVXnCJ0fIeZMxGovYfLmCcZxQog=
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=
@@ -55,6 +64,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -104,6 +115,8 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
@@ -119,8 +132,12 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.4-0.20190131011033-7dc38fb350b1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mitchellh/mapstructure v1.0.0 h1:vVpGvMXJPqSDh2VYHF7gsfQj8Ncx+Xw5Y1KHeTRY+7I=
github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mohae/deepcopy v0.0.0-20170308212314-bb9b5e7adda9/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
@@ -128,6 +145,9 @@ github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59P
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.2-0.20181111125026-1722abf79c2f/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -146,9 +166,19 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg=
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.2.1 h1:bIcUwXqLseLF3BDAZduuNfekWG87ibtFxi59Bq+oI9M=
github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -196,6 +226,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -205,6 +236,7 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -220,6 +252,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2By
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -242,6 +275,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20u
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -314,6 +348,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=

View File

@@ -10,6 +10,8 @@ cleanup() {
if [[ -n "$pid" && -d "/proc/$pid" ]]; then kill $pid; fi
docker rm -f host1 host2 host3
make clean
sleep 3
if [[ -n "$pid" && -d "/proc/$pid" ]]; then echo "process still running?"; exit 1; fi
set -e
}
cleanup
@@ -95,6 +97,24 @@ for ((i = 0; i < $N; i++)); do
done
set +x
echo "Testing SOCKS4a mode"
set -x
for ((i = 0; i < $N; i++)); do
for f in host1 host2 host3; do
curl -fsS -o /dev/null --socks4a http://127.0.0.1:18081 http://${f}:8080
done
done
set +x
echo "Testing SOCKS5h mode"
set -x
for ((i = 0; i < $N; i++)); do
for f in host1 host2 host3; do
curl -fsS -o /dev/null --socks5-hostname http://127.0.0.1:18081 http://${f}:8080
done
done
set +x
echo "iperf3 from host2 to host1"
docker exec host1 iperf3 -s > /dev/null &
iperf3_exec_pid=$!

View File

@@ -4,6 +4,8 @@ hosts:
vip: "127.0.42.100"
http:
listen: "127.0.0.1:18080"
socks:
listen: "127.0.0.1:18081"
host1:
cmd: "docker exec -i host1 /mnt/norouter"
vip: "127.0.42.101"

View File

@@ -26,6 +26,7 @@ import (
agenthttp "github.com/norouter/norouter/pkg/agent/http"
"github.com/norouter/norouter/pkg/agent/loopback"
agentsocks "github.com/norouter/norouter/pkg/agent/socks"
"github.com/norouter/norouter/pkg/bicopy/bicopyutil"
"github.com/norouter/norouter/pkg/netstackutil"
"github.com/norouter/norouter/pkg/stream"
@@ -156,23 +157,52 @@ func (a *Agent) configure(args *jsonmsg.ConfigureRequestArgs) error {
}
}
}
if a.config.HTTP.Listen != "" {
logrus.Debugf("http listen=%q", a.config.HTTP.Listen)
l, err := net.Listen("tcp", a.config.HTTP.Listen)
if err != nil {
if err := a.configureHTTP(); err != nil {
return err
}
httpHandler, err := agenthttp.NewHandler(a.stack, a.config.HostnameMap)
if err != nil {
return err
}
srv := &http.Server{Handler: httpHandler}
go srv.Serve(l)
}
if a.config.SOCKS.Listen != "" {
if err := a.configureSOCKS(); err != nil {
return err
}
}
go a.sendL3Routine()
return nil
}
func (a *Agent) configureHTTP() error {
logrus.Debugf("http listen=%q", a.config.HTTP.Listen)
l, err := net.Listen("tcp", a.config.HTTP.Listen)
if err != nil {
return err
}
httpHandler, err := agenthttp.NewHandler(a.stack, a.config.HostnameMap)
if err != nil {
return err
}
srv := &http.Server{Handler: httpHandler}
go srv.Serve(l)
return nil
}
func (a *Agent) configureSOCKS() error {
logrus.Debugf("socks listen=%q (supports SOCKS4/4a/5)", a.config.SOCKS.Listen)
l, err := net.Listen("tcp", a.config.SOCKS.Listen)
if err != nil {
return err
}
srv, err := agentsocks.NewServer(a.stack, a.config.HostnameMap)
if err != nil {
return err
}
go srv.Serve(l)
return nil
}
func (a *Agent) goGonetForward(me net.IP, f jsonmsg.Forward) error {
if f.Proto != "tcp" {
return errors.Errorf("expected proto be \"tcp\", got %q", f.Proto)

79
pkg/agent/socks/socks.go Normal file
View File

@@ -0,0 +1,79 @@
/*
Copyright (C) NoRouter authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package socks
import (
"context"
"net"
"github.com/cybozu-go/usocksd/socks"
"github.com/pkg/errors"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
func NewServer(st *stack.Stack, hostnameMap map[string]net.IP) (*socks.Server, error) {
d, err := NewDialer(st, hostnameMap)
if err != nil {
return nil, err
}
s := &socks.Server{
Dialer: d,
}
return s, nil
}
func NewDialer(st *stack.Stack, hostnameMap map[string]net.IP) (socks.Dialer, error) {
d := &dialer{
stack: st,
hostnameMap: hostnameMap,
}
return d, nil
}
type dialer struct {
stack *stack.Stack
hostnameMap map[string]net.IP
}
func (d *dialer) Dial(req *socks.Request) (net.Conn, error) {
ip := req.IP
if len(ip) == 0 {
if req.Hostname != "" {
if parsed := net.ParseIP(req.Hostname); len(parsed) != 0 {
ip = parsed
}
if resolved, ok := d.hostnameMap[req.Hostname]; ok {
ip = resolved
}
}
}
if len(ip) == 0 {
reqWithoutPassword := *req
if reqWithoutPassword.Password != "" {
reqWithoutPassword.Password = "********"
}
return nil, errors.Errorf("failed to determine IP for request %+v", reqWithoutPassword)
}
fullAddr := tcpip.FullAddress{
Addr: tcpip.Address(ip),
Port: uint16(req.Port),
}
return gonet.DialContextTCP(context.TODO(), d.stack, fullAddr, ipv4.ProtocolNumber)
}

View File

@@ -83,6 +83,7 @@ func NewCmdClient(ctx context.Context, hostname string, pm *parsed.ParsedManifes
configRequestArgs.HostnameMap[k] = v.VIP
}
configRequestArgs.HTTP.Listen = h.HTTP.Listen
configRequestArgs.SOCKS.Listen = h.SOCKS.Listen
configRequestArgs.Loopback.Disable = h.Loopback.Disable
configRequestArgsB, err := json.Marshal(configRequestArgs)
if err != nil {

View File

@@ -182,6 +182,13 @@ func (r *Manager) validateAgentFeatures(vip string, data jsonmsg.ConfigureResult
vip, version.FeatureHTTP, cc.configRequestArgs.HTTP.Listen)
}
}
if cc.configRequestArgs.SOCKS.Listen != "" {
if _, ok := fm[version.FeatureSOCKS]; !ok {
// not a critical error
logrus.Warnf("%s lacks feature %q, SOCKS listen (%q) is ignored",
vip, version.FeatureSOCKS, cc.configRequestArgs.SOCKS.Listen)
}
}
if cc.configRequestArgs.Loopback.Disable {
if _, ok := fm[version.FeatureDisableLoopback]; !ok {
return errors.Errorf("manifest has Loopback.Disable, but %s lacks feature %q, aborting for security purpose",

View File

@@ -54,6 +54,9 @@ type Host struct {
// HTTP can be specified since NoRouter v0.4.0
HTTP *HTTP `yaml:"http,omitempty"`
// SOCKS can be specified since NoRouter v0.4.0
SOCKS *SOCKS `yaml:"socks,omitempty"`
// Loopback can be specified since NoRouter v0.4.0
Loopback *Loopback `yaml:"loopback,omitempty"`
}
@@ -66,6 +69,16 @@ type HTTP struct {
Listen string `yaml:"listen,omitempty"`
}
// SOCKS can be specified since NoRouter v0.4.0
type SOCKS struct {
// Listen specifies an address of SOCKS proxy to be listened by NoRouter agent processes.
// The address is typically a local address, e.g. "127.0.0.1:18081".
// When the address is not specified, SOCKS proxy is disabled.
//
// Supported protocol versions: SOCKS4, SOCKS4a, and SOCKS5
Listen string `yaml:"listen,omitempty"`
}
// Loopback can be specified since NoRouter v0.4.0
type Loopback struct {
// Disable disables listening on multi-loopback addresses such as 127.0.42.100, 127.0.42.101...

View File

@@ -38,17 +38,22 @@ type Host struct {
VIP net.IP
Ports []*jsonmsg.Forward
HTTP HTTP
SOCKS SOCKS
Loopback Loopback
}
type Loopback struct {
Disable bool
}
type HTTP struct {
Listen string
}
type SOCKS struct {
Listen string
}
type Loopback struct {
Disable bool
}
func New(raw *manifest.Manifest) (*ParsedManifest, error) {
if ht := raw.HostTemplate; ht != nil {
if ht.VIP != "" {
@@ -105,6 +110,9 @@ func New(raw *manifest.Manifest) (*ParsedManifest, error) {
if raw.HostTemplate.HTTP != nil {
h.HTTP.Listen = raw.HostTemplate.HTTP.Listen
}
if raw.HostTemplate.SOCKS != nil {
h.SOCKS.Listen = raw.HostTemplate.SOCKS.Listen
}
if raw.HostTemplate.Loopback != nil {
h.Loopback.Disable = raw.HostTemplate.Loopback.Disable
}
@@ -112,6 +120,9 @@ func New(raw *manifest.Manifest) (*ParsedManifest, error) {
if rh.HTTP != nil {
h.HTTP.Listen = rh.HTTP.Listen
}
if rh.SOCKS != nil {
h.SOCKS.Listen = rh.SOCKS.Listen
}
if rh.Loopback != nil {
h.Loopback.Disable = rh.Loopback.Disable
}

View File

@@ -34,6 +34,7 @@ type ConfigureRequestArgs struct {
// Fields added in v0.4.0
HostnameMap map[string]net.IP `json:"hostnameMap,omitempty"` // hostname -> ip
HTTP HTTP `json:"http,omitempty"`
SOCKS SOCKS `json:"socks,omitempty"`
Loopback Loopback `json:"loopback,omitempty"`
}
@@ -60,6 +61,10 @@ type HTTP struct {
Listen string `json:"listen,omitempty"`
}
type SOCKS struct {
Listen string `json:"listen,omitempty"`
}
type Loopback struct {
Disable bool `json:"disable,omitempty"`
}

View File

@@ -25,8 +25,9 @@ const (
// Features introduced in v0.4.0:
FeatureHTTP = "http" // Listening on HTTP for proxy
FeatureDisableLoopback = "disable-loopback" // Disabling loopback
FeatureSOCKS = "socks" // Listening a SOCKS proxy (SOCKS4, SOCKS4a, and SOCKS5)
// Features introduced in vX.Y.Z:
// ...
)
var Features = []Feature{FeatureLoopback, FeatureTCP, FeatureHTTP, FeatureDisableLoopback}
var Features = []Feature{FeatureLoopback, FeatureTCP, FeatureHTTP, FeatureDisableLoopback, FeatureSOCKS}