Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix: track JetBrains connections#10968

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
code-asher merged 12 commits intomainfromjetbrains/track_connections
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from1 commit
Commits
Show all changes
12 commits
Select commitHold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
PrevPrevious commit
NextNext commit
Implement port process inspection
  • Loading branch information
@code-asher
code-asher committedDec 1, 2023
commitadf2fb37a942cb7b1885ae692262103e79355517
9 changes: 6 additions & 3 deletionsagent/agent_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -192,10 +192,13 @@ func TestAgent_Stats_Magic(t *testing.T) {
require.NoError(t, err)
})

// This test namebeing "Jetbrains" is required to be a certain string.
//It must match the regex checkin theagent for Jetbrains.
t.Run("Jetbrains", func(t *testing.T) {
// This test namemust contain the string checked for by the agent, since it
//looks for this stringin theprocess name.
t.Run("TracksIdea.vendor.name=JetBrains", func(t *testing.T) {
t.Parallel()
if runtime.GOOS != "linux" {
t.Skip("JetBrains tracking is only supported on Linux")
}
ctx := testutil.Context(t, testutil.WaitLong)

rl, err := net.Listen("tcp", "127.0.0.1:0")
Expand Down
2 changes: 1 addition & 1 deletionagent/agentssh/agentssh.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -113,7 +113,7 @@ func NewServer(ctx context.Context, logger slog.Logger, prometheusRegistry *prom
ChannelHandlers: map[string]ssh.ChannelHandler{
"direct-tcpip": func(srv *ssh.Server, conn *gossh.ServerConn, newChan gossh.NewChannel, ctx ssh.Context) {
// wrapper is designed to find and track jetbrains gateway connections.
wrapped := NewChannelAcceptWatcher(s.logger, newChan, &s.connCountJetBrains)
wrapped := NewChannelAcceptWatcher(ctx,s.logger, newChan, &s.connCountJetBrains)
ssh.DirectTCPIPHandler(srv, conn, wrapped, ctx)
},
"direct-streamlocal@openssh.com": directStreamLocalHandler,
Expand Down
32 changes: 26 additions & 6 deletionsagent/agentssh/jetbrainstrack.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
package agentssh

import (
"strings"
"sync"

"cdr.dev/slog"
"github.com/gliderlabs/ssh"
"go.uber.org/atomic"
gossh "golang.org/x/crypto/ssh"
)
Expand All@@ -21,17 +23,35 @@ type ChannelAcceptWatcher struct {
jetbrainsCounter *atomic.Int64
}

func NewChannelAcceptWatcher(logger slog.Logger, newChannel gossh.NewChannel, counter *atomic.Int64) gossh.NewChannel {
func NewChannelAcceptWatcher(ctx ssh.Context,logger slog.Logger, newChannel gossh.NewChannel, counter *atomic.Int64) gossh.NewChannel {
d := localForwardChannelData{}
if err := gossh.Unmarshal(newChannel.ExtraData(), &d); err != nil {
// If the data fails to unmarshal, do nothing
// If the data fails to unmarshal, do nothing.
return newChannel
}

//if !jetbrains {
// If this isn't jetbrains, then we don't need to do anything special.
//return newChannel
//}
// If we do get a port, we should be able to get the matching PID and from
// there look up the invocation.
cmdline, err := getListeningPortProcessCmdline(d.DestPort)
if err != nil {
logger.Warn(ctx, "port inspection failed",
slog.F("destination_port", d.DestPort),
slog.Error(err))
return newChannel
}
logger.Debug(ctx, "checking forwarded process",
slog.F("cmdline", cmdline),
slog.F("destination_port", d.DestPort))

// If this is not JetBrains, then we do not need to do anything special. We
// attempt to match on something that appears unique to JetBrains software and
// the vendor name flag seems like it might be a reasonable choice.
if !strings.Contains(strings.ToLower(cmdline), "idea.vendor.name=jetbrains") {
return newChannel
}

logger.Debug(ctx, "discovered forwarded JetBrains process",
slog.F("destination_port", d.DestPort))

return &ChannelAcceptWatcher{
NewChannel: newChannel,
Expand Down
31 changes: 31 additions & 0 deletionsagent/agentssh/portinspection_supported.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
//go:build linux

package agentssh

import (
"fmt"
"os"

"github.com/cakturk/go-netstat/netstat"
"golang.org/x/xerrors"
)

func getListeningPortProcessCmdline(port uint32) (string, error) {
tabs, err := netstat.TCPSocks(func(s *netstat.SockTabEntry) bool {
return s.LocalAddr != nil && uint32(s.LocalAddr.Port) == port
})
if err != nil {
return "", xerrors.Errorf("inspect port %d: %w", port, err)
}
if len(tabs) == 0 {
return "", nil
}
// The process name provided by go-netstat does not include the full command
// line so grab that instead.
pid := tabs[0].Process.Pid
data, err := os.ReadFile(fmt.Sprintf("/proc/%d/cmdline", pid))
if err != nil {
return "", xerrors.Errorf("read /proc/%d/cmdline: %w", pid, err)
}
return string(data), nil
}
9 changes: 9 additions & 0 deletionsagent/agentssh/portinspection_unsupported.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
//go:build !linux

package agentssh

func getListeningPortProcessCmdline(port uint32) (string, error) {
// We are not worrying about other platforms at the moment because Gateway
// only supports Linux anyway.
return "", nil
}

[8]ページ先頭

©2009-2025 Movatter.jp