Skip to content
/linux-syscalls

Network · Section 2

connect(2)

Initiate a connection on a socket — TCP handshake, UDP destination set, or AF_UNIX rendezvous.

Signature

#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr * addr, socklen_t addrlen);
sockfd
Socket descriptor (any type that supports connect()).
addr
Pointer to a sockaddr_* struct describing the destination.
addrlen
Size of the struct (sizeof(struct sockaddr_in) etc.).

Description

connect() initiates a connection on the socket referred to by sockfd to the address specified by addr. For SOCK_STREAM (TCP), this triggers the three-way handshake; the call returns 0 when ESTABLISHED, or -1/EINPROGRESS immediately on a non-blocking socket (with the actual outcome later observable via getsockopt(SO_ERROR) after the socket becomes writable). For SOCK_DGRAM, connect() doesn't generate traffic — it just remembers the remote address so that subsequent send()/recv() calls (without explicit destination) use it, and incoming datagrams from other peers are filtered out. For AF_UNIX, connect() rendezvous with a listening peer at the given path. Clients usually call socket() → (optional bind for source-port pinning) → connect(); skipping bind lets the kernel pick an ephemeral source port.

Architecture mapping

ArchitectureNumberABIEntry point
x86 (i386)362i386sys_connect
x64 (x86_64)42commonsys_connect
ARM64 (aarch64)203sys_connect

Kernel history

Introduced in Linux 1.0.

  1. 1.0

    connect() has been part of Linux since 1.0 with BSD semantics.

  2. 4.11

    TCP Fast Open client support landed; with TCP_FASTOPEN_CONNECT socket option, connect() can carry application data in the SYN, eliminating one RTT for HTTPS connections to a server that previously sent a TFO cookie.

seccomp & containers

Docker default profile

Allowed

Podman default profile

Allowed

connect() is on every default profile. The most useful hardening is at the destination level: cgroup BPF (BPF_CGROUP_INET4_CONNECT / INET6_CONNECT) can deny connections to specific IPs / ports / sets — used by Cilium and Kubernetes NetworkPolicy to enforce egress rules without iptables. seccomp argument filtering on sockaddr* is technically possible but awkward because the address is read by the kernel from user memory; the cgroup-BPF path is cleaner.

libseccomp

seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(connect), 0);

strace example

$ strace -e socket,connect curl -s https://example.com -o /dev/null
socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_TCP) = 5
connect(5, {sa_family=AF_INET6, sin6_port=htons(443), sin6_addr=…}, 28) = -1 EINPROGRESS

strace decodes sockaddr fully. EINPROGRESS is benign on non-blocking sockets — chase the subsequent poll/epoll_wait for the real outcome. A connect() that immediately returns ECONNREFUSED is the host-is-up-port-is-not signature; ETIMEDOUT after ~127 s is the firewalled/dropped pattern. Combine with -e network for the full conversation.

Security & observability

connect() is the canonical primitive of data exfiltration and C2 callouts. eBPF tracepoint sys_enter_connect with the decoded sockaddr is the right observation point; pair with /proc/<pid>/exe to attribute. Container EDRs (Falco rule: 'Outbound Connection to C2 Server') match destination IPs against threat-intel feeds at this hook. AF_UNIX connect() to /var/run/docker.sock from a non-root container is the classic 'Docker socket escape' indicator. Reverse-shell payloads typically call socket(AF_INET) → connect() → dup2 to stdin/stdout/stderr → execve('/bin/sh') — the connect to a non-RFC1918 IP from a workload that should only talk to its sidecars is a strong signal.

Errors

EACCES
An iptables/nftables rule rejected the outgoing connection; or AF_UNIX path permission denial.
EADDRINUSE
EAFNOSUPPORT
EAGAIN
EALREADY
A previous non-blocking connect() is still in progress.
EBADF
ECONNREFUSED
Active reset from the destination — TCP RST in response to SYN, or UDP port unreachable ICMP. The remote host is up but nothing is listening (or a firewall is sending RSTs).
EINPROGRESS
Non-blocking socket and the handshake is in flight. Wait for POLLOUT on the fd and check SO_ERROR.
EINTR
EISCONN
Socket is already connected.
ENETUNREACH
No route to the destination network. Routing-table problem.
ENOTSOCK
ETIMEDOUT
No response within the kernel's connect timeout (tcp_syn_retries — ~127 s on default Linux). The host is unreachable or filtered.

Related syscalls