imsvr.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package imsvr
  2. import (
  3. "github.com/xtaci/kcp-go"
  4. "net"
  5. "golang.org/x/crypto/ssh"
  6. "errors"
  7. "bytes"
  8. )
  9. const VERSION string = "1.0"
  10. type Server struct{
  11. kcpListener *net.Listener
  12. sshConfig *ssh.ServerConfig
  13. isPasswdAuthSet bool
  14. cliAuthCallback func(username string, password []byte) bool
  15. sbnatAuthList map[string][]byte
  16. }
  17. func NewServer(conf *ServerConfig) (*Server, error) {
  18. kcplis,err := kcp.Listen(conf.BindAddress)
  19. if err != nil {
  20. return nil, err
  21. }
  22. sshcfg := &ssh.ServerConfig{
  23. NoClientAuth: false,
  24. MaxAuthTries: conf.MaxAuthTries,
  25. ServerVersion: "goSBNAT-Intermediate-Server-" + VERSION,
  26. }
  27. if conf.hostkeys == nil {
  28. return nil, errors.New("NoHostKeySpecified")
  29. }
  30. for _,v := range conf.hostkeys {
  31. sshcfg.AddHostKey(v)
  32. }
  33. svr := &Server{
  34. kcpListener: &kcplis,
  35. sshConfig: sshcfg,
  36. }
  37. if conf.ovrSSHKeyboardInteractiveCallback {
  38. svr.sshConfig.KeyboardInteractiveCallback = conf.ocSSHKeyboardInteractiveCallback
  39. }else {
  40. svr.sshConfig.KeyboardInteractiveCallback = svr.sshKbdIaCb
  41. }
  42. if conf.ovrSSHAuthLogCallback {
  43. svr.sshConfig.AuthLogCallback = conf.ocSSHAuthLogCallback
  44. }else{
  45. svr.sshConfig.AuthLogCallback = svr.sshAuthLogCb
  46. }
  47. if conf.ovrSSHPasswordCallback {
  48. svr.sshConfig.PasswordCallback = conf.ocSSHPasswordCallback
  49. }else {
  50. svr.sshConfig.PasswordCallback = svr.sshPwdCb
  51. }
  52. if conf.ovrSSHPublicKeyCallback {
  53. svr.sshConfig.PublicKeyCallback = conf.ocSSHPublicKeyCallback
  54. }else {
  55. svr.sshConfig.PublicKeyCallback = svr.sshPubKeyCb
  56. }
  57. svr.sbnatAuthList = make(map[string][]byte)
  58. return svr, nil
  59. }
  60. func (this *Server) sshKbdIaCb(conn ssh.ConnMetadata, client ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error){
  61. return nil, errors.New("KeyboardInteractiveAuthNotSupport")
  62. }
  63. func (this *Server) sshAuthLogCb(conn ssh.ConnMetadata, method string, err error){
  64. return
  65. }
  66. func (this *Server) sshPwdCb(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
  67. if this.cliAuthCallback == nil {
  68. return nil, errors.New("NoClientAuthCallback")
  69. }
  70. if this.cliAuthCallback(conn.User(), password) {
  71. perm := &ssh.Permissions{
  72. CriticalOptions: make(map[string]string),
  73. Extensions: make(map[string]string),
  74. }
  75. perm.CriticalOptions["type"] = "client"
  76. perm.CriticalOptions["user"] = conn.User()
  77. return perm, nil
  78. }else {
  79. return nil, errors.New("ClientAuthFailed")
  80. }
  81. }
  82. func (this *Server) sshPubKeyCb(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
  83. v, ok := this.sbnatAuthList[conn.User()]
  84. if ok {
  85. if bytes.Equal(v, key.Marshal()) {
  86. perm := &ssh.Permissions{
  87. CriticalOptions: make(map[string]string),
  88. Extensions: make(map[string]string),
  89. }
  90. perm.CriticalOptions["type"] = "sbnat"
  91. perm.CriticalOptions["user"] = conn.User()
  92. return perm, nil
  93. }else {
  94. return nil, errors.New("FailedAuthSBNAT")
  95. }
  96. }else{
  97. return nil, errors.New("FailedAuthSBNAT")
  98. }
  99. }
  100. func (this *Server) AddAuthOfSBNAT(servername string, pubkey ssh.PublicKey) {
  101. this.sbnatAuthList[servername] = pubkey.Marshal()
  102. }
  103. func (this *Server) RegistClientAuthCallback(cb func(username string, password []byte) bool) {
  104. this.cliAuthCallback = cb
  105. }