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:
Nico Berlee 2023-03-06 01:21:08 +01:00 committed by Andrey Smirnov
parent fda6da6929
commit 97048f7c37
No known key found for this signature in database
GPG Key ID: 7B26396447AB6DFD
15 changed files with 4124 additions and 592 deletions

View File

@ -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;
}

View 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
View File

@ -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
View File

@ -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=

View File

@ -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]

View File

@ -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
}

View File

@ -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),

View File

@ -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)

View 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

View File

@ -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

View File

@ -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
}

View File

@ -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 -->

View File

@ -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