feat: netstat in API and client
Implements netstat in Talos API and client (talosctl). Signed-off-by: Nico Berlee <nico.berlee@on2it.net> Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
This commit is contained in:
parent
fda6da6929
commit
97048f7c37
@ -99,6 +99,7 @@ service MachineService {
|
||||
rpc GenerateClientConfiguration(GenerateClientConfigurationRequest) returns (GenerateClientConfigurationResponse);
|
||||
// PacketCapture performs packet capture and streams back pcap file.
|
||||
rpc PacketCapture(PacketCaptureRequest) returns (stream common.Data);
|
||||
rpc Netstat(NetstatRequest) returns (NetstatResponse);
|
||||
}
|
||||
|
||||
// rpc applyConfiguration
|
||||
@ -1194,3 +1195,81 @@ message BPFInstruction {
|
||||
uint32 jf = 3;
|
||||
uint32 k = 4;
|
||||
}
|
||||
|
||||
message NetstatRequest {
|
||||
enum Filter {
|
||||
ALL = 0;
|
||||
CONNECTED = 1;
|
||||
LISTENING = 2;
|
||||
}
|
||||
Filter filter = 1;
|
||||
message Feature {
|
||||
bool pid = 1;
|
||||
}
|
||||
Feature feature = 2;
|
||||
message L4proto {
|
||||
bool tcp = 1;
|
||||
bool tcp6 = 2;
|
||||
bool udp = 3;
|
||||
bool udp6 = 4;
|
||||
bool udplite = 5;
|
||||
bool udplite6 = 6;
|
||||
bool raw = 7;
|
||||
bool raw6 = 8;
|
||||
}
|
||||
L4proto l4proto = 3;
|
||||
}
|
||||
|
||||
message ConnectRecord {
|
||||
string l4proto = 1;
|
||||
string localip = 2;
|
||||
uint32 localport = 3;
|
||||
string remoteip = 4;
|
||||
uint32 remoteport = 5;
|
||||
enum State {
|
||||
RESERVED = 0;
|
||||
ESTABLISHED = 1;
|
||||
SYN_SENT = 2;
|
||||
SYN_RECV = 3;
|
||||
FIN_WAIT1 = 4;
|
||||
FIN_WAIT2 = 5;
|
||||
TIME_WAIT = 6;
|
||||
CLOSE = 7;
|
||||
CLOSEWAIT = 8;
|
||||
LASTACK = 9;
|
||||
LISTEN = 10;
|
||||
CLOSING = 11;
|
||||
}
|
||||
State state = 6;
|
||||
uint64 txqueue = 7;
|
||||
uint64 rxqueue = 8;
|
||||
enum TimerActive {
|
||||
OFF = 0;
|
||||
ON = 1;
|
||||
KEEPALIVE = 2;
|
||||
TIMEWAIT = 3;
|
||||
PROBE = 4;
|
||||
}
|
||||
TimerActive tr = 9;
|
||||
uint64 timerwhen = 10;
|
||||
uint64 retrnsmt = 11;
|
||||
uint32 uid = 12;
|
||||
uint64 timeout = 13;
|
||||
uint64 inode = 14;
|
||||
uint64 ref = 15;
|
||||
uint64 pointer = 16;
|
||||
message Process {
|
||||
uint32 pid = 1;
|
||||
string name = 2;
|
||||
}
|
||||
Process process = 17;
|
||||
}
|
||||
|
||||
message Netstat {
|
||||
common.Metadata metadata = 1;
|
||||
repeated ConnectRecord connectrecord = 2;
|
||||
}
|
||||
|
||||
message NetstatResponse {
|
||||
repeated Netstat messages = 1;
|
||||
}
|
||||
|
255
cmd/talosctl/cmd/talos/netstat.go
Normal file
255
cmd/talosctl/cmd/talos/netstat.go
Normal file
@ -0,0 +1,255 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/cli"
|
||||
"github.com/siderolabs/talos/pkg/machinery/api/machine"
|
||||
"github.com/siderolabs/talos/pkg/machinery/client"
|
||||
)
|
||||
|
||||
var netstatCmdFlags struct {
|
||||
verbose bool
|
||||
extend bool
|
||||
pid bool
|
||||
timers bool
|
||||
listening bool
|
||||
all bool
|
||||
tcp bool
|
||||
udp bool
|
||||
udplite bool
|
||||
raw bool
|
||||
ipv4 bool
|
||||
ipv6 bool
|
||||
}
|
||||
|
||||
// netstatCmd represents the ls command.
|
||||
var netstatCmd = &cobra.Command{
|
||||
Use: "netstat",
|
||||
Aliases: []string{"ss"},
|
||||
Short: "Retrieve a socket listing of connections",
|
||||
Long: ``,
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return WithClient(func(ctx context.Context, c *client.Client) error {
|
||||
req := netstatFlagsToRequest()
|
||||
response, err := c.Netstat(ctx, req)
|
||||
if err != nil {
|
||||
if response == nil {
|
||||
return fmt.Errorf("error getting netstat: %w", err)
|
||||
}
|
||||
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
err = printNetstat(response)
|
||||
|
||||
return err
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func netstatFlagsToRequest() *machine.NetstatRequest {
|
||||
req := machine.NetstatRequest{
|
||||
Feature: &machine.NetstatRequest_Feature{
|
||||
Pid: netstatCmdFlags.pid,
|
||||
},
|
||||
L4Proto: &machine.NetstatRequest_L4Proto{
|
||||
Tcp: netstatCmdFlags.tcp,
|
||||
Tcp6: netstatCmdFlags.tcp,
|
||||
Udp: netstatCmdFlags.udp,
|
||||
Udp6: netstatCmdFlags.udp,
|
||||
Udplite: netstatCmdFlags.udplite,
|
||||
Udplite6: netstatCmdFlags.udplite,
|
||||
Raw: netstatCmdFlags.raw,
|
||||
Raw6: netstatCmdFlags.raw,
|
||||
},
|
||||
}
|
||||
|
||||
switch {
|
||||
case netstatCmdFlags.all:
|
||||
req.Filter = machine.NetstatRequest_ALL
|
||||
case netstatCmdFlags.listening:
|
||||
req.Filter = machine.NetstatRequest_LISTENING
|
||||
default:
|
||||
req.Filter = machine.NetstatRequest_CONNECTED
|
||||
}
|
||||
|
||||
if netstatCmdFlags.verbose {
|
||||
req.L4Proto.Tcp = true
|
||||
req.L4Proto.Tcp6 = true
|
||||
req.L4Proto.Udp = true
|
||||
req.L4Proto.Udp6 = true
|
||||
req.L4Proto.Udplite = true
|
||||
req.L4Proto.Udplite6 = true
|
||||
req.L4Proto.Raw = true
|
||||
req.L4Proto.Raw6 = true
|
||||
}
|
||||
|
||||
if !req.L4Proto.Tcp && !req.L4Proto.Tcp6 && !req.L4Proto.Udp && !req.L4Proto.Udp6 && !req.L4Proto.Udplite && !req.L4Proto.Udplite6 && !req.L4Proto.Raw && !req.L4Proto.Raw6 {
|
||||
req.L4Proto.Tcp = true
|
||||
req.L4Proto.Tcp6 = true
|
||||
req.L4Proto.Udp = true
|
||||
req.L4Proto.Udp6 = true
|
||||
}
|
||||
|
||||
if netstatCmdFlags.ipv4 && !netstatCmdFlags.ipv6 {
|
||||
req.L4Proto.Tcp6 = false
|
||||
req.L4Proto.Udp6 = false
|
||||
req.L4Proto.Udplite6 = false
|
||||
req.L4Proto.Raw6 = false
|
||||
}
|
||||
|
||||
if netstatCmdFlags.ipv6 && !netstatCmdFlags.ipv4 {
|
||||
req.L4Proto.Tcp = false
|
||||
req.L4Proto.Udp = false
|
||||
req.L4Proto.Udplite = false
|
||||
req.L4Proto.Raw = false
|
||||
}
|
||||
|
||||
return &req
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func printNetstat(response *machine.NetstatResponse) error {
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
node := ""
|
||||
|
||||
labels := strings.Join(
|
||||
[]string{
|
||||
"Proto",
|
||||
"Recv-Q",
|
||||
"Send-Q",
|
||||
"Local Address",
|
||||
"Foreign Address",
|
||||
"State",
|
||||
}, "\t")
|
||||
|
||||
if netstatCmdFlags.extend {
|
||||
labels += "\t" + strings.Join(
|
||||
[]string{
|
||||
"Uid",
|
||||
"Inode",
|
||||
}, "\t")
|
||||
}
|
||||
|
||||
if netstatCmdFlags.pid {
|
||||
labels += "\t" + "PID/Program name"
|
||||
}
|
||||
|
||||
if netstatCmdFlags.timers {
|
||||
labels += "\t" + "Timer"
|
||||
}
|
||||
|
||||
for i, message := range response.Messages {
|
||||
if message.Metadata != nil && message.Metadata.Hostname != "" {
|
||||
node = message.Metadata.Hostname
|
||||
}
|
||||
|
||||
if len(message.Connectrecord) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for j, record := range message.Connectrecord {
|
||||
if i == 0 && j == 0 {
|
||||
if node != "" {
|
||||
fmt.Fprintln(w, "NODE\t"+labels)
|
||||
} else {
|
||||
fmt.Fprintln(w, labels)
|
||||
}
|
||||
}
|
||||
|
||||
args := []interface{}{}
|
||||
|
||||
if node != "" {
|
||||
args = append(args, node)
|
||||
}
|
||||
|
||||
state := ""
|
||||
if record.State != 7 {
|
||||
state = record.State.String()
|
||||
}
|
||||
|
||||
args = append(args, []interface{}{
|
||||
record.L4Proto,
|
||||
strconv.FormatUint(record.Rxqueue, 10),
|
||||
strconv.FormatUint(record.Txqueue, 10),
|
||||
fmt.Sprintf("%s:%d", record.Localip, record.Localport),
|
||||
fmt.Sprintf("%s:%s", record.Remoteip, wildcardIfZero(record.Remoteport)),
|
||||
state,
|
||||
}...)
|
||||
|
||||
if netstatCmdFlags.extend {
|
||||
args = append(args, []interface{}{
|
||||
strconv.FormatUint(uint64(record.Uid), 10),
|
||||
strconv.FormatUint(record.Inode, 10),
|
||||
}...)
|
||||
}
|
||||
|
||||
if netstatCmdFlags.pid {
|
||||
if record.Process.Pid != 0 {
|
||||
args = append(args, []interface{}{
|
||||
fmt.Sprintf("%d/%s", record.Process.Pid, record.Process.Name),
|
||||
}...)
|
||||
} else {
|
||||
args = append(args, []interface{}{
|
||||
"-",
|
||||
}...)
|
||||
}
|
||||
}
|
||||
|
||||
if netstatCmdFlags.timers {
|
||||
timerwhen := strconv.FormatFloat(float64(record.Timerwhen)/100, 'f', 2, 64)
|
||||
|
||||
args = append(args, []interface{}{
|
||||
fmt.Sprintf("%s (%s/%d/%d)", strings.ToLower(record.Tr.String()), timerwhen, record.Retrnsmt, record.Timeout),
|
||||
}...)
|
||||
}
|
||||
|
||||
pattern := strings.Repeat("%s\t", len(args))
|
||||
pattern = strings.TrimSpace(pattern) + "\n"
|
||||
|
||||
fmt.Fprintf(w, pattern, args...)
|
||||
}
|
||||
}
|
||||
|
||||
return w.Flush()
|
||||
}
|
||||
|
||||
func wildcardIfZero(num uint32) string {
|
||||
if num == 0 {
|
||||
return "*"
|
||||
}
|
||||
|
||||
return strconv.FormatUint(uint64(num), 10)
|
||||
}
|
||||
|
||||
func init() {
|
||||
netstatCmd.Flags().BoolVarP(&netstatCmdFlags.verbose, "verbose", "v", false, "display sockets of all supported transport protocols")
|
||||
// extend is normally -e but cannot be used as this is endpoint in talosctl
|
||||
netstatCmd.Flags().BoolVarP(&netstatCmdFlags.extend, "extend", "x", false, "show detailed socket information")
|
||||
netstatCmd.Flags().BoolVarP(&netstatCmdFlags.pid, "programs", "p", false, "show process using socket")
|
||||
netstatCmd.Flags().BoolVarP(&netstatCmdFlags.timers, "timers", "o", false, "display timers")
|
||||
netstatCmd.Flags().BoolVarP(&netstatCmdFlags.listening, "listening", "l", false, "display listening server sockets")
|
||||
netstatCmd.Flags().BoolVarP(&netstatCmdFlags.all, "all", "a", false, "display all sockets states (default: connected)")
|
||||
netstatCmd.Flags().BoolVarP(&netstatCmdFlags.tcp, "tcp", "t", false, "display only TCP sockets")
|
||||
netstatCmd.Flags().BoolVarP(&netstatCmdFlags.udp, "udp", "u", false, "display only UDP sockets")
|
||||
netstatCmd.Flags().BoolVarP(&netstatCmdFlags.udplite, "udplite", "U", false, "display only UDPLite sockets")
|
||||
netstatCmd.Flags().BoolVarP(&netstatCmdFlags.raw, "raw", "w", false, "display only RAW sockets")
|
||||
netstatCmd.Flags().BoolVarP(&netstatCmdFlags.ipv4, "ipv4", "4", false, "display only ipv4 sockets")
|
||||
netstatCmd.Flags().BoolVarP(&netstatCmdFlags.ipv4, "ipv6", "6", false, "display only ipv6 sockets")
|
||||
|
||||
addCommand(netstatCmd)
|
||||
}
|
1
go.mod
1
go.mod
@ -75,6 +75,7 @@ require (
|
||||
github.com/mdlayher/genetlink v1.3.1
|
||||
github.com/mdlayher/netlink v1.7.1
|
||||
github.com/mdlayher/netx v0.0.0-20220422152302-c711c2f8512f
|
||||
github.com/nberlee/go-netstat v0.0.0-20230306184515-0b1bbade8369
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
||||
github.com/packethost/packngo v0.29.0
|
||||
|
2
go.sum
2
go.sum
@ -973,6 +973,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/nberlee/go-netstat v0.0.0-20230306184515-0b1bbade8369 h1:0impfFsYpeJ96ao5NPNlyjwlQ/YNHhBY3oxriCSHyZA=
|
||||
github.com/nberlee/go-netstat v0.0.0-20230306184515-0b1bbade8369/go.mod h1:GvDCRLsUKMRN1wULkt7tpnDmjSIE6YGf5zeVq+mBO64=
|
||||
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d h1:x3S6kxmy49zXVVyhcnrFqxvNVCBPb2KZ9hV2RBdS840=
|
||||
|
@ -118,10 +118,17 @@ rebooting, shutting down a node, accessing packet capture, etcd alarm APIs, etcd
|
||||
"""
|
||||
|
||||
[notes.containers-output]
|
||||
title = "Talosctl containers"
|
||||
title = "talosctl containers"
|
||||
description="""\
|
||||
`talosctl logs -k` and `talosctl containers -k` now support and output container display names with their ids.
|
||||
This allows to distinguish between containers with the same name.
|
||||
"""
|
||||
|
||||
[notes.netstat]
|
||||
title = "talosctl netstat"
|
||||
description="""\
|
||||
Talos API was extended to support retrieving a list of network connections (sockets) from the node.
|
||||
`talosctl netstat` command was added to retrieve the list of network connections.
|
||||
"""
|
||||
|
||||
[make_deps]
|
||||
|
@ -33,6 +33,7 @@ import (
|
||||
"github.com/google/gopacket/pcapgo"
|
||||
"github.com/google/uuid"
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
"github.com/nberlee/go-netstat/netstat"
|
||||
"github.com/prometheus/procfs"
|
||||
"github.com/rs/xid"
|
||||
"github.com/siderolabs/gen/slices"
|
||||
@ -2344,3 +2345,82 @@ func upgradeMutex(c *etcd.Client) (*concurrency.Mutex, error) {
|
||||
|
||||
return mu, nil
|
||||
}
|
||||
|
||||
// Netstat implements the machine.MachineServer interface.
|
||||
func (s *Server) Netstat(ctx context.Context, req *machine.NetstatRequest) (*machine.NetstatResponse, error) {
|
||||
if req == nil {
|
||||
req = new(machine.NetstatRequest)
|
||||
}
|
||||
|
||||
features := netstat.EnableFeatures{
|
||||
TCP: req.L4Proto.Tcp,
|
||||
TCP6: req.L4Proto.Tcp6,
|
||||
UDP: req.L4Proto.Udp,
|
||||
UDP6: req.L4Proto.Udp6,
|
||||
UDPLite: req.L4Proto.Udplite,
|
||||
UDPLite6: req.L4Proto.Udplite6,
|
||||
Raw: req.L4Proto.Raw,
|
||||
Raw6: req.L4Proto.Raw6,
|
||||
PID: req.Feature.Pid,
|
||||
}
|
||||
|
||||
var fn netstat.AcceptFn
|
||||
|
||||
switch req.Filter {
|
||||
case machine.NetstatRequest_ALL:
|
||||
fn = func(*netstat.SockTabEntry) bool { return true }
|
||||
case machine.NetstatRequest_LISTENING:
|
||||
fn = func(s *netstat.SockTabEntry) bool {
|
||||
return s.State == netstat.Listen
|
||||
}
|
||||
case machine.NetstatRequest_CONNECTED:
|
||||
fn = func(s *netstat.SockTabEntry) bool {
|
||||
return s.State != netstat.Listen
|
||||
}
|
||||
}
|
||||
|
||||
netstatResp, err := netstat.Netstat(ctx, features, fn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
records := make([]*machine.ConnectRecord, len(netstatResp))
|
||||
|
||||
for i, entry := range netstatResp {
|
||||
records[i] = &machine.ConnectRecord{
|
||||
L4Proto: entry.Transport,
|
||||
Localip: entry.LocalEndpoint.IP.String(),
|
||||
Localport: uint32(entry.LocalEndpoint.Port),
|
||||
Remoteip: entry.RemoteEndpoint.IP.String(),
|
||||
Remoteport: uint32(entry.RemoteEndpoint.Port),
|
||||
State: machine.ConnectRecord_State(entry.State),
|
||||
Txqueue: entry.TxQueue,
|
||||
Rxqueue: entry.RxQueue,
|
||||
Tr: machine.ConnectRecord_TimerActive(entry.Tr),
|
||||
Timerwhen: entry.TimerWhen,
|
||||
Retrnsmt: entry.Retrnsmt,
|
||||
Uid: entry.UID,
|
||||
Timeout: entry.Timeout,
|
||||
Inode: entry.Inode,
|
||||
Ref: entry.Ref,
|
||||
Pointer: entry.Pointer,
|
||||
Process: &machine.ConnectRecord_Process{},
|
||||
}
|
||||
if entry.Process != nil {
|
||||
records[i].Process = &machine.ConnectRecord_Process{
|
||||
Pid: uint32(entry.Process.Pid),
|
||||
Name: entry.Process.Name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reply := &machine.NetstatResponse{
|
||||
Messages: []*machine.Netstat{
|
||||
{
|
||||
Connectrecord: records,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return reply, err
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ var rules = map[string]role.Set{
|
||||
"/machine.MachineService/Memory": role.MakeSet(role.Admin, role.Operator, role.Reader),
|
||||
"/machine.MachineService/Mounts": role.MakeSet(role.Admin, role.Operator, role.Reader),
|
||||
"/machine.MachineService/NetworkDeviceStats": role.MakeSet(role.Admin, role.Operator, role.Reader),
|
||||
"/machine.MachineService/Netstat": role.MakeSet(role.Admin, role.Operator, role.Reader),
|
||||
"/machine.MachineService/PacketCapture": role.MakeSet(role.Admin, role.Operator),
|
||||
"/machine.MachineService/Processes": role.MakeSet(role.Admin, role.Operator, role.Reader),
|
||||
"/machine.MachineService/Read": role.MakeSet(role.Admin),
|
||||
|
@ -226,10 +226,7 @@ DrainLoop:
|
||||
}
|
||||
}
|
||||
|
||||
if tailLines >= 0 {
|
||||
// we might expect one line to be streamed extra for concurrent request
|
||||
suite.Assert().InDelta(tailLines, linesDrained, 1)
|
||||
}
|
||||
suite.Assert().GreaterOrEqual(int32(linesDrained), tailLines)
|
||||
|
||||
// invoke machined API
|
||||
_, err = suite.Client.Stats(suite.nodeCtx, constants.SystemContainerdNamespace, common.ContainerDriver_CONTAINERD)
|
||||
|
33
internal/integration/cli/netstat.go
Normal file
33
internal/integration/cli/netstat.go
Normal file
@ -0,0 +1,33 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
//go:build integration_cli
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
"github.com/siderolabs/talos/internal/integration/base"
|
||||
)
|
||||
|
||||
// NetstatSuite verifies etcd command.
|
||||
type NetstatSuite struct {
|
||||
base.CLISuite
|
||||
}
|
||||
|
||||
// SuiteName ...
|
||||
func (suite *NetstatSuite) SuiteName() string {
|
||||
return "cli.NetstatSuite"
|
||||
}
|
||||
|
||||
// TestListening verifies that there are listening connections.
|
||||
func (suite *NetstatSuite) TestListening() {
|
||||
suite.RunCLI([]string{"netstat", "--listening", "--programs", "--tcp", "--extend", "--nodes", suite.RandomDiscoveredNodeInternalIP()},
|
||||
base.StdoutShouldMatch(regexp.MustCompile(`:::50000.+LISTEN.+/apid`)))
|
||||
}
|
||||
|
||||
func init() {
|
||||
allSuites = append(allSuites, new(NetstatSuite))
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -111,6 +111,7 @@ type MachineServiceClient interface {
|
||||
GenerateClientConfiguration(ctx context.Context, in *GenerateClientConfigurationRequest, opts ...grpc.CallOption) (*GenerateClientConfigurationResponse, error)
|
||||
// PacketCapture performs packet capture and streams back pcap file.
|
||||
PacketCapture(ctx context.Context, in *PacketCaptureRequest, opts ...grpc.CallOption) (MachineService_PacketCaptureClient, error)
|
||||
Netstat(ctx context.Context, in *NetstatRequest, opts ...grpc.CallOption) (*NetstatResponse, error)
|
||||
}
|
||||
|
||||
type machineServiceClient struct {
|
||||
@ -791,6 +792,15 @@ func (x *machineServicePacketCaptureClient) Recv() (*common.Data, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *machineServiceClient) Netstat(ctx context.Context, in *NetstatRequest, opts ...grpc.CallOption) (*NetstatResponse, error) {
|
||||
out := new(NetstatResponse)
|
||||
err := c.cc.Invoke(ctx, "/machine.MachineService/Netstat", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// MachineServiceServer is the server API for MachineService service.
|
||||
// All implementations must embed UnimplementedMachineServiceServer
|
||||
// for forward compatibility
|
||||
@ -880,6 +890,7 @@ type MachineServiceServer interface {
|
||||
GenerateClientConfiguration(context.Context, *GenerateClientConfigurationRequest) (*GenerateClientConfigurationResponse, error)
|
||||
// PacketCapture performs packet capture and streams back pcap file.
|
||||
PacketCapture(*PacketCaptureRequest, MachineService_PacketCaptureServer) error
|
||||
Netstat(context.Context, *NetstatRequest) (*NetstatResponse, error)
|
||||
mustEmbedUnimplementedMachineServiceServer()
|
||||
}
|
||||
|
||||
@ -1025,6 +1036,9 @@ func (UnimplementedMachineServiceServer) GenerateClientConfiguration(context.Con
|
||||
func (UnimplementedMachineServiceServer) PacketCapture(*PacketCaptureRequest, MachineService_PacketCaptureServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method PacketCapture not implemented")
|
||||
}
|
||||
func (UnimplementedMachineServiceServer) Netstat(context.Context, *NetstatRequest) (*NetstatResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Netstat not implemented")
|
||||
}
|
||||
func (UnimplementedMachineServiceServer) mustEmbedUnimplementedMachineServiceServer() {}
|
||||
|
||||
// UnsafeMachineServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
@ -1904,6 +1918,24 @@ func (x *machineServicePacketCaptureServer) Send(m *common.Data) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _MachineService_Netstat_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(NetstatRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MachineServiceServer).Netstat(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/machine.MachineService/Netstat",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MachineServiceServer).Netstat(ctx, req.(*NetstatRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// MachineService_ServiceDesc is the grpc.ServiceDesc for MachineService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@ -2051,6 +2083,10 @@ var MachineService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "GenerateClientConfiguration",
|
||||
Handler: _MachineService_GenerateClientConfiguration_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Netstat",
|
||||
Handler: _MachineService_Netstat_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -964,3 +964,18 @@ func ReadStream(stream MachineStream) (io.ReadCloser, <-chan error, error) {
|
||||
|
||||
return pr, errCh, stream.CloseSend()
|
||||
}
|
||||
|
||||
// Netstat lists the network sockets on the current node.
|
||||
func (c *Client) Netstat(ctx context.Context, req *machineapi.NetstatRequest, callOptions ...grpc.CallOption) (*machineapi.NetstatResponse, error) {
|
||||
resp, err := c.MachineClient.Netstat(
|
||||
ctx,
|
||||
req,
|
||||
callOptions...,
|
||||
)
|
||||
|
||||
var filtered interface{}
|
||||
filtered, err = FilterMessages(resp, err)
|
||||
resp, _ = filtered.(*machineapi.NetstatResponse) //nolint:errcheck
|
||||
|
||||
return resp, err
|
||||
}
|
||||
|
@ -224,6 +224,8 @@ description: Talos gRPC API reference.
|
||||
- [ClusterNetworkConfig](#machine.ClusterNetworkConfig)
|
||||
- [ConfigLoadErrorEvent](#machine.ConfigLoadErrorEvent)
|
||||
- [ConfigValidationErrorEvent](#machine.ConfigValidationErrorEvent)
|
||||
- [ConnectRecord](#machine.ConnectRecord)
|
||||
- [ConnectRecord.Process](#machine.ConnectRecord.Process)
|
||||
- [Container](#machine.Container)
|
||||
- [ContainerInfo](#machine.ContainerInfo)
|
||||
- [ContainersRequest](#machine.ContainersRequest)
|
||||
@ -294,6 +296,11 @@ description: Talos gRPC API reference.
|
||||
- [Mounts](#machine.Mounts)
|
||||
- [MountsResponse](#machine.MountsResponse)
|
||||
- [NetDev](#machine.NetDev)
|
||||
- [Netstat](#machine.Netstat)
|
||||
- [NetstatRequest](#machine.NetstatRequest)
|
||||
- [NetstatRequest.Feature](#machine.NetstatRequest.Feature)
|
||||
- [NetstatRequest.L4proto](#machine.NetstatRequest.L4proto)
|
||||
- [NetstatResponse](#machine.NetstatResponse)
|
||||
- [NetworkConfig](#machine.NetworkConfig)
|
||||
- [NetworkDeviceConfig](#machine.NetworkDeviceConfig)
|
||||
- [NetworkDeviceStats](#machine.NetworkDeviceStats)
|
||||
@ -356,10 +363,13 @@ description: Talos gRPC API reference.
|
||||
- [VersionResponse](#machine.VersionResponse)
|
||||
|
||||
- [ApplyConfigurationRequest.Mode](#machine.ApplyConfigurationRequest.Mode)
|
||||
- [ConnectRecord.State](#machine.ConnectRecord.State)
|
||||
- [ConnectRecord.TimerActive](#machine.ConnectRecord.TimerActive)
|
||||
- [EtcdMemberAlarm.AlarmType](#machine.EtcdMemberAlarm.AlarmType)
|
||||
- [ListRequest.Type](#machine.ListRequest.Type)
|
||||
- [MachineConfig.MachineType](#machine.MachineConfig.MachineType)
|
||||
- [MachineStatusEvent.MachineStage](#machine.MachineStatusEvent.MachineStage)
|
||||
- [NetstatRequest.Filter](#machine.NetstatRequest.Filter)
|
||||
- [PhaseEvent.Action](#machine.PhaseEvent.Action)
|
||||
- [RebootRequest.Mode](#machine.RebootRequest.Mode)
|
||||
- [ResetRequest.WipeMode](#machine.ResetRequest.WipeMode)
|
||||
@ -3938,6 +3948,53 @@ ConfigValidationErrorEvent is reported when config validation has failed.
|
||||
|
||||
|
||||
|
||||
<a name="machine.ConnectRecord"></a>
|
||||
|
||||
### ConnectRecord
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| l4proto | [string](#string) | | |
|
||||
| localip | [string](#string) | | |
|
||||
| localport | [uint32](#uint32) | | |
|
||||
| remoteip | [string](#string) | | |
|
||||
| remoteport | [uint32](#uint32) | | |
|
||||
| state | [ConnectRecord.State](#machine.ConnectRecord.State) | | |
|
||||
| txqueue | [uint64](#uint64) | | |
|
||||
| rxqueue | [uint64](#uint64) | | |
|
||||
| tr | [ConnectRecord.TimerActive](#machine.ConnectRecord.TimerActive) | | |
|
||||
| timerwhen | [uint64](#uint64) | | |
|
||||
| retrnsmt | [uint64](#uint64) | | |
|
||||
| uid | [uint32](#uint32) | | |
|
||||
| timeout | [uint64](#uint64) | | |
|
||||
| inode | [uint64](#uint64) | | |
|
||||
| ref | [uint64](#uint64) | | |
|
||||
| pointer | [uint64](#uint64) | | |
|
||||
| process | [ConnectRecord.Process](#machine.ConnectRecord.Process) | | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="machine.ConnectRecord.Process"></a>
|
||||
|
||||
### ConnectRecord.Process
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| pid | [uint32](#uint32) | | |
|
||||
| name | [string](#string) | | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="machine.Container"></a>
|
||||
|
||||
### Container
|
||||
@ -5142,6 +5199,91 @@ The messages message containing the requested df stats.
|
||||
|
||||
|
||||
|
||||
<a name="machine.Netstat"></a>
|
||||
|
||||
### Netstat
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| metadata | [common.Metadata](#common.Metadata) | | |
|
||||
| connectrecord | [ConnectRecord](#machine.ConnectRecord) | repeated | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="machine.NetstatRequest"></a>
|
||||
|
||||
### NetstatRequest
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| filter | [NetstatRequest.Filter](#machine.NetstatRequest.Filter) | | |
|
||||
| feature | [NetstatRequest.Feature](#machine.NetstatRequest.Feature) | | |
|
||||
| l4proto | [NetstatRequest.L4proto](#machine.NetstatRequest.L4proto) | | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="machine.NetstatRequest.Feature"></a>
|
||||
|
||||
### NetstatRequest.Feature
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| pid | [bool](#bool) | | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="machine.NetstatRequest.L4proto"></a>
|
||||
|
||||
### NetstatRequest.L4proto
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| tcp | [bool](#bool) | | |
|
||||
| tcp6 | [bool](#bool) | | |
|
||||
| udp | [bool](#bool) | | |
|
||||
| udp6 | [bool](#bool) | | |
|
||||
| udplite | [bool](#bool) | | |
|
||||
| udplite6 | [bool](#bool) | | |
|
||||
| raw | [bool](#bool) | | |
|
||||
| raw6 | [bool](#bool) | | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="machine.NetstatResponse"></a>
|
||||
|
||||
### NetstatResponse
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| messages | [Netstat](#machine.Netstat) | repeated | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="machine.NetworkConfig"></a>
|
||||
|
||||
### NetworkConfig
|
||||
@ -6150,6 +6292,43 @@ rpc upgrade
|
||||
|
||||
|
||||
|
||||
<a name="machine.ConnectRecord.State"></a>
|
||||
|
||||
### ConnectRecord.State
|
||||
|
||||
|
||||
| Name | Number | Description |
|
||||
| ---- | ------ | ----------- |
|
||||
| RESERVED | 0 | |
|
||||
| ESTABLISHED | 1 | |
|
||||
| SYN_SENT | 2 | |
|
||||
| SYN_RECV | 3 | |
|
||||
| FIN_WAIT1 | 4 | |
|
||||
| FIN_WAIT2 | 5 | |
|
||||
| TIME_WAIT | 6 | |
|
||||
| CLOSE | 7 | |
|
||||
| CLOSEWAIT | 8 | |
|
||||
| LASTACK | 9 | |
|
||||
| LISTEN | 10 | |
|
||||
| CLOSING | 11 | |
|
||||
|
||||
|
||||
|
||||
<a name="machine.ConnectRecord.TimerActive"></a>
|
||||
|
||||
### ConnectRecord.TimerActive
|
||||
|
||||
|
||||
| Name | Number | Description |
|
||||
| ---- | ------ | ----------- |
|
||||
| OFF | 0 | |
|
||||
| ON | 1 | |
|
||||
| KEEPALIVE | 2 | |
|
||||
| TIMEWAIT | 3 | |
|
||||
| PROBE | 4 | |
|
||||
|
||||
|
||||
|
||||
<a name="machine.EtcdMemberAlarm.AlarmType"></a>
|
||||
|
||||
### EtcdMemberAlarm.AlarmType
|
||||
@ -6209,6 +6388,19 @@ File type.
|
||||
|
||||
|
||||
|
||||
<a name="machine.NetstatRequest.Filter"></a>
|
||||
|
||||
### NetstatRequest.Filter
|
||||
|
||||
|
||||
| Name | Number | Description |
|
||||
| ---- | ------ | ----------- |
|
||||
| ALL | 0 | |
|
||||
| CONNECTED | 1 | |
|
||||
| LISTENING | 2 | |
|
||||
|
||||
|
||||
|
||||
<a name="machine.PhaseEvent.Action"></a>
|
||||
|
||||
### PhaseEvent.Action
|
||||
@ -6368,6 +6560,7 @@ This method is available only on control plane nodes (which run etcd). |
|
||||
| Version | [.google.protobuf.Empty](#google.protobuf.Empty) | [VersionResponse](#machine.VersionResponse) | |
|
||||
| GenerateClientConfiguration | [GenerateClientConfigurationRequest](#machine.GenerateClientConfigurationRequest) | [GenerateClientConfigurationResponse](#machine.GenerateClientConfigurationResponse) | GenerateClientConfiguration generates talosctl client configuration (talosconfig). |
|
||||
| PacketCapture | [PacketCaptureRequest](#machine.PacketCaptureRequest) | [.common.Data](#common.Data) stream | PacketCapture performs packet capture and streams back pcap file. |
|
||||
| Netstat | [NetstatRequest](#machine.NetstatRequest) | [NetstatResponse](#machine.NetstatResponse) | |
|
||||
|
||||
<!-- end services -->
|
||||
|
||||
|
@ -2012,6 +2012,46 @@ talosctl mounts [flags]
|
||||
|
||||
* [talosctl](#talosctl) - A CLI for out-of-band management of Kubernetes nodes created by Talos
|
||||
|
||||
## talosctl netstat
|
||||
|
||||
Retrieve a socket listing of connections
|
||||
|
||||
```
|
||||
talosctl netstat [flags]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-a, --all display all sockets states (default: connected)
|
||||
-x, --extend show detailed socket information
|
||||
-h, --help help for netstat
|
||||
-4, --ipv4 display only ipv4 sockets
|
||||
-6, --ipv6 display only ipv6 sockets
|
||||
-l, --listening display listening server sockets
|
||||
-p, --programs show process using socket
|
||||
-w, --raw display only RAW sockets
|
||||
-t, --tcp display only TCP sockets
|
||||
-o, --timers display timers
|
||||
-u, --udp display only UDP sockets
|
||||
-U, --udplite display only UDPLite sockets
|
||||
-v, --verbose display sockets of all supported transport protocols
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--cluster string Cluster to connect to if a proxy endpoint is used.
|
||||
--context string Context to be used in command
|
||||
-e, --endpoints strings override default endpoints in Talos configuration
|
||||
-n, --nodes strings target the specified nodes
|
||||
--talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order.
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [talosctl](#talosctl) - A CLI for out-of-band management of Kubernetes nodes created by Talos
|
||||
|
||||
## talosctl patch
|
||||
|
||||
Update field(s) of a resource using a JSON patch.
|
||||
@ -2679,6 +2719,7 @@ A CLI for out-of-band management of Kubernetes nodes created by Talos
|
||||
* [talosctl machineconfig](#talosctl-machineconfig) - Machine config related commands
|
||||
* [talosctl memory](#talosctl-memory) - Show memory usage
|
||||
* [talosctl mounts](#talosctl-mounts) - List mounts
|
||||
* [talosctl netstat](#talosctl-netstat) - Retrieve a socket listing of connections
|
||||
* [talosctl patch](#talosctl-patch) - Update field(s) of a resource using a JSON patch.
|
||||
* [talosctl pcap](#talosctl-pcap) - Capture the network packets from the node.
|
||||
* [talosctl processes](#talosctl-processes) - List running processes
|
||||
|
Loading…
x
Reference in New Issue
Block a user