diff --git a/obfssh_client/config.go b/obfssh_client/config.go new file mode 100644 index 0000000..ca34b17 --- /dev/null +++ b/obfssh_client/config.go @@ -0,0 +1,37 @@ +package main + +import ( + "github.com/go-yaml/yaml" + "io/ioutil" +) + +type config struct { + Host string `yaml:"host"` + Port int `yaml:"port"` + PrivateKey string `yaml:"private_key"` + ObfsMethod string `yaml:"obfs_method"` + ObfsKey string `yaml:"obfs_key"` + Username string `yaml:"username"` + Password string `yaml:"password"` + KeepaliveInterval int `yaml:"keepalive_interval"` + KeepaliveMax int `yaml:"keepalive_max"` + Debug bool `yaml:"debug"` + DisableObfsAfterHandshake bool `yaml:"disable_obfs_after_handshake"` + NotRunCmd bool `yaml:"not_run_cmd"` + LocalForward []string `yaml:"local_forward"` + RemoteForward []string `yaml:"remote_forward"` + DynamicForward []string `yaml:"dynamic_forward"` +} + +func loadConfig(f string) (*config, error) { + buf, err := ioutil.ReadFile(f) + if err != nil { + return nil, err + } + var c config + err = yaml.Unmarshal(buf, &c) + if err != nil { + return nil, err + } + return &c, nil +} diff --git a/obfssh_client/config_example.yaml b/obfssh_client/config_example.yaml new file mode 100644 index 0000000..6ff7b99 --- /dev/null +++ b/obfssh_client/config_example.yaml @@ -0,0 +1,54 @@ + +# vim: set ft=yaml: + +# the server address +host: ssh.example.com + +# the server port +port: 2223 + +# obfs encrypt method, rc4, aes or none, same as server +obfs_method: rc4 + +# obfs encrypt key, same as server +obfs_key: some_keyword + +# ssh username at remote +username: user1 + +# ssh password +password: 1234 + +# keep alive interval +keepalive_interval: 15 + +# max error on keep alive +# when error meet max count, will close the connection +keepalive_max: 5 + +# private key to auth user on remote +private_key: /home/user1/.ssh/id_rsa + +# debug +debug: false + +# not run cmd or start shell on remote +not_run_cmd: true + +# disable obfs after ssh handshake +disable_obfs_after_handshake: true + +# local port forward, forword local port to remote host +local_forward: + - :3311:127.0.0.1:3121 + - 127.0.0.1:3121:10.0.0.1:1223 + +# remote port forward, forward remote port to local host +remote_forward: + - :3123:127.0.0.1:4322 + - :3124:10.0.0.1:2212 + +# dynamic forward port to remote host +dynamic_forward: + - :3224 + - 127.0.0.1:9883 diff --git a/obfssh_client/config_test.go b/obfssh_client/config_test.go new file mode 100644 index 0000000..9c11537 --- /dev/null +++ b/obfssh_client/config_test.go @@ -0,0 +1,14 @@ +package main + +import ( + "fmt" + "testing" +) + +func TestConfig(t *testing.T) { + c, err := loadConfig("config_example.yaml") + if err != nil { + t.Error(err) + } + fmt.Printf("%+v\n", c) +} diff --git a/obfssh_client/ssh.go b/obfssh_client/ssh.go index 8a6755f..2166104 100644 --- a/obfssh_client/ssh.go +++ b/obfssh_client/ssh.go @@ -36,7 +36,8 @@ func (lf *stringSlice) String() string { } func main() { - var host, port, user, pass, key string + var host, user, pass, key string + var port int var method, encryptKey string var notRunCmd bool var debug bool @@ -47,9 +48,12 @@ func main() { var remoteForwards stringSlice var dynamicForwards stringSlice + var configfile string + + flag.StringVar(&configfile, "f", "", "configure file") flag.StringVar(&user, "l", os.Getenv("USER"), "ssh username") flag.StringVar(&pass, "pw", "", "ssh password") - flag.StringVar(&port, "p", "22", "remote port") + flag.IntVar(&port, "p", 22, "remote port") flag.StringVar(&key, "i", "", "private key file") flag.Var(&localForwards, "L", "forward local port to remote, format [local_host:]local_port:remote_host:remote_port") flag.Var(&remoteForwards, "R", "forward remote port to local, format [remote_host:]remote_port:local_host:local_port") @@ -63,6 +67,57 @@ func main() { flag.BoolVar(&disableObfsAfterHandshake, "disable_obfs_after_handshake", false, "disable obfs after handshake") flag.Parse() + if configfile != "" { + if c, err := loadConfig(configfile); err == nil { + if c.Host != "" { + host = c.Host + } + if c.Username != "" { + user = c.Username + } + if c.Password != "" { + pass = c.Password + } + if c.Port != 0 { + port = c.Port + } + if c.PrivateKey != "" { + key = c.PrivateKey + } + if c.ObfsMethod != "" { + method = c.ObfsMethod + } + if c.ObfsKey != "" { + encryptKey = c.ObfsKey + } + if c.Debug { + debug = c.Debug + } + if c.DisableObfsAfterHandshake { + disableObfsAfterHandshake = c.DisableObfsAfterHandshake + } + if c.NotRunCmd { + notRunCmd = c.NotRunCmd + } + if c.KeepaliveInterval != 0 { + keepAliveInterval = c.KeepaliveInterval + } + if c.KeepaliveMax != 0 { + keepAliveMax = c.KeepaliveMax + } + + if len(c.LocalForward) != 0 { + localForwards = append(localForwards, c.LocalForward...) + } + if len(c.RemoteForward) != 0 { + remoteForwards = append(remoteForwards, c.RemoteForward...) + } + if len(c.DynamicForward) != 0 { + dynamicForwards = append(dynamicForwards, c.DynamicForward...) + } + } + } + if debug { obfssh.SSHLogLevel = obfssh.DEBUG } @@ -112,16 +167,20 @@ func main() { args := flag.Args() var cmd string - switch len(args) { - case 0: - flag.PrintDefaults() - log.Fatal("you must specify the remote host") - case 1: - host = args[0] - cmd = "" - default: - host = args[0] - cmd = strings.Join(args[1:], " ") + if host == "" { + switch len(args) { + case 0: + flag.PrintDefaults() + log.Fatal("you must specify the remote host") + case 1: + host = args[0] + cmd = "" + default: + host = args[0] + cmd = strings.Join(args[1:], " ") + } + } else { + cmd = strings.Join(args, " ") } if strings.Contains(host, "@") { @@ -161,7 +220,7 @@ func main() { Timeout: 10 * time.Second, } - rhost := net.JoinHostPort(host, port) + rhost := net.JoinHostPort(host, fmt.Sprintf("%d", port)) c, err := net.Dial("tcp", rhost) if err != nil {