shazow / ssh-chat

Chat over SSH.

Home Page:https://shazow.net/posts/ssh-how-does-it-even/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

bug: Zombie users (reproduceable)

opened this issue · comments

Expected Behavior

User will be kicked when the moderator types

/kick user

Actual Behavior

When using a certain client and exiting, the user lingers and cannot be kicked or banned until restarting the server.

Steps to reproduce behavior

  1. Get an android phone.
  2. Download the app termius from the Google Play Store.
  3. Open the app and click on continue without account.
  4. Go to hosts, click on new host, and enter the details such as your username. Make sure to enter ssh.chat as the IP address.
  5. Once you've successfully ssh into the ssh.chat, completely close the app but leave it running in the background. (This can be done by just swiping the app away). Now let your phone idle on battery saving mode for a long time (I'd say around 45 minutes).
  6. Go back to the app, and swipe right to reveal a menu. Go to terminal, which will show you a list of active terminals.
  7. Finally, close the terminal by pressing the close button. The user should linger and is unable to be kicked or banned.

Additional Comments

This bug is extremely hard to reproduce intentionally and requires some patience.

I noticed that the client for the un-kickable users was SSH-2.0-libssh2_1.9.0_DEV (maybe this can be produced with other apps that support this type of client?).

Android version: 7
Battery Saving: On
SSH Client: Termius

cc @voldyman you were looking at this before, any interest in investigating? :)

This is interesting, what happens when you try to kick the user after they've reached this state?

@voldyman The usual zombie behaviour we saw before,

12:01  onelegend_: I found a possible bug
12:02  [🍮 shazow] which was...
12:03  onelegend_: try kicing onelegend
12:03  onelegend_: or Guest2458
12:03  [🍮 shazow] /kick onelegend
12:03   * onelegend was kicked by 🍮 shazow.
12:03  [🍮 shazow] /whois onelegend
12:03  -> name: onelegend
 > ip: [snip]
 > fingerprint: (no public key)
 > client: SSH-2.0-libssh2_1.9.0_DEV
 > joined: 2.6 days ago

Maybe a good way is to setup a server with a debugger attached/tracing, and try connecting and dropping from termius.

yeah, that would be a good starting point.

Having trouble reproducing locally T_T

$ ssh-anon -p 2022 localhost
Warning: Permanently added '[localhost]:2022' (RSA) to the list of known hosts.
 * shazow joined. (Connected: 1)
 * Guest1 joined. (Connected: 2)
 * Guest1 left. (After 2 seconds)
 * shazow left. (After 3 minutes)
 * shazow joined. (Connected: 1)
shazow: test
 * Guest3 joined. (Connected: 2)
[Guest3] hi
[Guest3] ping shazow
 * shazow left. (After 65 seconds)
 * u0_a241 joined. (Connected: 2)
u0_a241: hi
[Guest3] /whois u0_a241
-> name: u0_a241
 > fingerprint: (no public key)
 > client: SSH-2.0-OpenSSH_8.0
 > joined: 4 seconds ago
 * shazow joined. (Connected: 3)
[Guest3] /whois shazow
-> name: shazow
 > fingerprint: (no public key)
 > client: SSH-2.0-libssh2_1.9.0_DEV
 > joined: 4 seconds ago
[Guest3] /whois shazow
-> name: shazow
 > fingerprint: (no public key)
 > client: SSH-2.0-libssh2_1.9.0_DEV
 > joined: 99 seconds ago
 * shazow left. (After 9 minutes)
 * u0_a241 left. (After 12 minutes)
[Guest3] /whois shazow
-> Err: user not found

cc @shazow Wait until you can't physically type in the terminal to close it.

@epicgoldenlife I haven't been able to get it to that state, any other tips? I find the user disconnects within a few minutes of swiping away the app, at least on Android 11.

I'd say instead of swiping away the app, try just pressing the home key and locking the screen. I know this isn't part of the original procedure to reproduce this bug, but I think android may have been aggressively killing the app in your case.

Tried that too, still can't reproduce it. :( Can you try running the latest master ssh-chat locally and connecting to it from your phone and see if you can reproduce it locally?

I also noticed that when I connect to sshchat and then hibernate my windows device, the user stays connected for a few minutes, and I'm even able to resume the session like nothing happened when the computer is booted up again.

I spun up a dedicated server to populate with zombies, and we got some success. Here are the results.

Debug logs: (It seems zombies1-5 were indeed zombies, though zombie5 might have zombified in a special way?)

...
2021-03-31 21:26:51.071 DEBUG [:48516] Joined: zombie
[chat/message] 2021/03/31 22:27:35 Write failed to zombie, closing: write tcp :4242->:48516: write: connection reset by peer
2021-04-01 09:51:56.193 DEBUG [:51278] Joined: zombie2
2021-04-01 09:53:26.017 DEBUG [:51295] Joined: zombie3
2021-04-01 09:53:53.882 DEBUG [:51296] Joined: Guest12
2021-04-01 10:29:54.867 DEBUG [:51345] Joined: Guest13
[chat/message] 2021/04/01 10:29:54 Write failed to zombie2, closing: EOF
[chat/message] 2021/04/01 10:29:54 Write failed to zombie3, closing: EOF
[chat/message] 2021/04/01 10:29:54 Write failed to zombie4, closing: EOF
2021-04-01 10:37:01.495 DEBUG [:51379] Joined: Guest14
2021-04-01 10:40:26.700 DEBUG [:51345] Leaving: zombie5
2021-04-01 10:40:27.399 DEBUG [:51379] Leaving: shaz0w
2021-04-01 10:47:16.192 DEBUG [:51410] Joined: zombie5
2021-04-01 11:41:50.235 DEBUG [:34086] Leaving: onelegend
[chat/message] 2021/04/01 11:41:50 Write failed to zombie5, closing: write tcp :4242->:51410: write: connection reset by peer
[sshd] 2021/04/01 12:30:35 [:57341] Failed to handshake: ssh: overflow reading version string
2021-04-01 12:44:29.330 DEBUG [:28524] Joined: onelegend
2021-04-01 12:44:40.158 DEBUG [:56582] Joined: shazow
2021-04-01 12:45:27.678 DEBUG [:28524] Leaving: onelegend
2021-04-01 12:45:36.147 DEBUG [:56582] Leaving: shazow
[sshd] 2021/04/01 12:45:55 [:56592] Failed to handshake: ssh: overflow reading version string
[sshd] 2021/04/01 12:45:56 [:56590] Failed to handshake: ssh: overflow reading version string
[sshd] 2021/04/01 12:46:16 [:56594] Failed to handshake: read tcp :4242->:56594: i/o timeout

pprof goroutine dump:

goroutine profile: total 36
5 @ 0x43a8e5 0x4059fa 0x405755 0x69ffdd 0x69fa57 0x69f6f5 0x470f21
#	0x69ffdc	golang.org/x/crypto/ssh.(*mux).handleChannelOpen+0x23c	/home/shazow/local/go/pkg/mod/golang.org/x/crypto@v0.0.0-20210322153248-0c34fe9e7dc2/ssh/mux.go:293
#	0x69fa56	golang.org/x/crypto/ssh.(*mux).onePacket+0x216		/home/shazow/local/go/pkg/mod/golang.org/x/crypto@v0.0.0-20210322153248-0c34fe9e7dc2/ssh/mux.go:231
#	0x69f6f4	golang.org/x/crypto/ssh.(*mux).loop+0x34		/home/shazow/local/go/pkg/mod/golang.org/x/crypto@v0.0.0-20210322153248-0c34fe9e7dc2/ssh/mux.go:190

5 @ 0x43a8e5 0x4068cf 0x40654b 0x6807c5 0x6d8aa5 0x470f21
#	0x6807c4	golang.org/x/crypto/ssh.(*channel).SendRequest+0x284	/home/shazow/local/go/pkg/mod/golang.org/x/crypto@v0.0.0-20210322153248-0c34fe9e7dc2/ssh/channel.go:591
#	0x6d8aa4	github.com/shazow/ssh-chat/sshd.NewTerminal.func1+0x104	/home/shazow/local/go/src/github.com/shazow/ssh-chat/sshd/terminal.go:122

5 @ 0x43a8e5 0x4068cf 0x40654b 0x68655e 0x470f21
#	0x68655d	golang.org/x/crypto/ssh.DiscardRequests+0x3d	/home/shazow/local/go/pkg/mod/golang.org/x/crypto@v0.0.0-20210322153248-0c34fe9e7dc2/ssh/connection.go:80

5 @ 0x43a8e5 0x4068cf 0x40654b 0x6d7c05 0x470f21
#	0x6d7c04	github.com/shazow/ssh-chat/sshd.(*Terminal).listen+0x64	/home/shazow/local/go/src/github.com/shazow/ssh-chat/sshd/terminal.go:181

5 @ 0x43a8e5 0x46d2f8 0x46d2ce 0x478879 0x67b3bc 0x67ef7c 0x6801fb 0x6d4edd 0x6d4b16 0x6ecca5 0x6d8989 0x470f21
#	0x46d2cd	sync.runtime_notifyListWait+0xcd					/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/runtime/sema.go:513
#	0x478878	sync.(*Cond).Wait+0x98							/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/sync/cond.go:56
#	0x67b3bb	golang.org/x/crypto/ssh.(*buffer).Read+0x1db				/home/shazow/local/go/pkg/mod/golang.org/x/crypto@v0.0.0-20210322153248-0c34fe9e7dc2/ssh/buffer.go:94
#	0x67ef7b	golang.org/x/crypto/ssh.(*channel).ReadExtended+0x1fb			/home/shazow/local/go/pkg/mod/golang.org/x/crypto@v0.0.0-20210322153248-0c34fe9e7dc2/ssh/channel.go:351
#	0x6801fa	golang.org/x/crypto/ssh.(*channel).Read+0x5a				/home/shazow/local/go/pkg/mod/golang.org/x/crypto@v0.0.0-20210322153248-0c34fe9e7dc2/ssh/channel.go:528
#	0x6d4edc	github.com/shazow/ssh-chat/sshd/terminal.(*Terminal).readLine+0x33c	/home/shazow/local/go/src/github.com/shazow/ssh-chat/sshd/terminal/terminal.go:833
#	0x6d4b15	github.com/shazow/ssh-chat/sshd/terminal.(*Terminal).ReadLine+0x75	/home/shazow/local/go/src/github.com/shazow/ssh-chat/sshd/terminal/terminal.go:763
#	0x6ecca4	github.com/shazow/ssh-chat.(*Host).Connect+0x544			/home/shazow/local/go/src/github.com/shazow/ssh-chat/host.go:187
#	0x6d8988	github.com/shazow/ssh-chat/sshd.(*SSHListener).Serve.func1+0x148	/home/shazow/local/go/src/github.com/shazow/ssh-chat/sshd/net.go:72

2 @ 0x43a8e5 0x4059fa 0x405755 0x687265 0x470f21
#	0x687264	golang.org/x/crypto/ssh.(*handshakeTransport).readLoop+0xc4	/home/shazow/local/go/pkg/mod/golang.org/x/crypto@v0.0.0-20210322153248-0c34fe9e7dc2/ssh/handshake.go:207

2 @ 0x43a8e5 0x44b897 0x687638 0x470f21
#	0x687637	golang.org/x/crypto/ssh.(*handshakeTransport).kexLoop+0xd7	/home/shazow/local/go/pkg/mod/golang.org/x/crypto@v0.0.0-20210322153248-0c34fe9e7dc2/ssh/handshake.go:268

1 @ 0x40c5b4 0x46d865 0x65bce5 0x470f21
#	0x46d864	os/signal.signal_recv+0xa4	/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/runtime/sigqueue.go:168
#	0x65bce4	os/signal.loop+0x24		/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/os/signal/signal_unix.go:23

1 @ 0x43a8e5 0x4068cf 0x40650b 0x72a1b6 0x43a4b6 0x470f21
#	0x72a1b5	main.main+0xbf5		/home/shazow/local/go/src/github.com/shazow/ssh-chat/cmd/ssh-chat/cmd.go:242
#	0x43a4b5	runtime.main+0x255	/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/runtime/proc.go:225

1 @ 0x43a8e5 0x4068cf 0x40654b 0x6e462f 0x470f21
#	0x6e462e	github.com/shazow/ssh-chat/chat.(*Room).Serve+0x8e	/home/shazow/local/go/src/github.com/shazow/ssh-chat/chat/room.go:125

1 @ 0x43a8e5 0x432f3b 0x46b675 0x4d3b25 0x4d5232 0x4d5214 0x56b4e5 0x57e712 0x57d6a5 0x64aa25 0x64a73a 0x72b01c 0x72af62 0x470f21
#	0x46b674	internal/poll.runtime_pollWait+0x54		/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/runtime/netpoll.go:222
#	0x4d3b24	internal/poll.(*pollDesc).wait+0x44		/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/internal/poll/fd_poll_runtime.go:87
#	0x4d5231	internal/poll.(*pollDesc).waitRead+0x211	/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/internal/poll/fd_poll_runtime.go:92
#	0x4d5213	internal/poll.(*FD).Accept+0x1f3		/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/internal/poll/fd_unix.go:401
#	0x56b4e4	net.(*netFD).accept+0x44			/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/fd_unix.go:172
#	0x57e711	net.(*TCPListener).accept+0x31			/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/tcpsock_posix.go:139
#	0x57d6a4	net.(*TCPListener).Accept+0x64			/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/tcpsock.go:261
#	0x64aa24	net/http.(*Server).Serve+0x284			/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/http/server.go:2981
#	0x64a739	net/http.(*Server).ListenAndServe+0xb9		/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/http/server.go:2910
#	0x72b01b	net/http.ListenAndServe+0xdb			/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/http/server.go:3164
#	0x72af61	main.main.func1+0x21				/home/shazow/local/go/src/github.com/shazow/ssh-chat/cmd/ssh-chat/cmd.go:81

1 @ 0x43a8e5 0x432f3b 0x46b675 0x4d3b25 0x4d5232 0x4d5214 0x56b4e5 0x57e712 0x57d6a5 0x6d69b3 0x6edbd3 0x470f21
#	0x46b674	internal/poll.runtime_pollWait+0x54				/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/runtime/netpoll.go:222
#	0x4d3b24	internal/poll.(*pollDesc).wait+0x44				/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/internal/poll/fd_poll_runtime.go:87
#	0x4d5231	internal/poll.(*pollDesc).waitRead+0x211			/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/internal/poll/fd_poll_runtime.go:92
#	0x4d5213	internal/poll.(*FD).Accept+0x1f3				/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/internal/poll/fd_unix.go:401
#	0x56b4e4	net.(*netFD).accept+0x44					/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/fd_unix.go:172
#	0x57e711	net.(*TCPListener).accept+0x31					/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/tcpsock_posix.go:139
#	0x57d6a4	net.(*TCPListener).Accept+0x64					/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/tcpsock.go:261
#	0x6d69b2	github.com/shazow/ssh-chat/sshd.(*SSHListener).Serve+0x92	/home/shazow/local/go/src/github.com/shazow/ssh-chat/sshd/net.go:57
#	0x6edbd2	github.com/shazow/ssh-chat.(*Host).Serve+0x72			/home/shazow/local/go/src/github.com/shazow/ssh-chat/host.go:241

1 @ 0x46b27d 0x71862e 0x718405 0x714f92 0x726865 0x7280b7 0x647844 0x6496cd 0x64a643 0x64658d 0x470f21
#	0x46b27c	runtime/pprof.runtime_goroutineProfileWithLabels+0x5c	/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/runtime/mprof.go:716
#	0x71862d	runtime/pprof.writeRuntimeProfile+0xcd			/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/runtime/pprof/pprof.go:724
#	0x718404	runtime/pprof.writeGoroutine+0xa4			/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/runtime/pprof/pprof.go:684
#	0x714f91	runtime/pprof.(*Profile).WriteTo+0x3f1			/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/runtime/pprof/pprof.go:331
#	0x726864	net/http/pprof.handler.ServeHTTP+0x384			/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/http/pprof/pprof.go:253
#	0x7280b6	net/http/pprof.Index+0x8d6				/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/http/pprof/pprof.go:371
#	0x647843	net/http.HandlerFunc.ServeHTTP+0x43			/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/http/server.go:2069
#	0x6496cc	net/http.(*ServeMux).ServeHTTP+0x1ac			/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/http/server.go:2448
#	0x64a642	net/http.serverHandler.ServeHTTP+0xa2			/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/http/server.go:2887
#	0x64658c	net/http.(*conn).serve+0x8cc				/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/http/server.go:1952

1 @ 0x63fd41 0x470f21
#	0x63fd40	net/http.(*connReader).backgroundRead+0x0	/nix/store/8an9pj9rd4izn7bjkr5nzrnw07zrdjz6-go-1.16.2/share/go/src/net/http/server.go:691