Erlang interface to low level socket operations
Erlang C
Switch branches/tags
Nothing to show
Clone or download
Pull request Compare This branch is 122 commits behind msantos:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

procket is an Erlang library for socket creation and manipulation.

procket uses a setuid helper so actions like binding low ports and requesting some sockets types can be done while Erlang is running as an unprivileged user.


Other features include:

  • low level socket manipulation using socket/3, ioctl/3, setsockopt/4, ...

  • support any protocols supported by the socket interface: ICMP, Unix sockets, ...

  • support for the BSD raw socket interface

  • generate and snoop packets using PF_PACKET sockets on Linux

  • generate and snoop packets using the BPF interface on BSDs like Mac OS X

  • support for creating and reading/writing from character devices like TUN/TAP interfaces


procket may work with any version of Erlang after R14A but using the latest Erlang release is advisable.



  • IPv6 support


  • procket:listen/1,2 has been renamed procket:open/1,2. procket:listen/2 is now a wrapper around listen(2)

  • procket:recvfrom/2 returns {error,eagain} when data is not available (previously return nodata)


open(Port, Options) -> {ok, FD} | {error, Reason} | {error, {Reason, Description}}

    Types   Port = 0..65535
            Options = [Opts]
            Opts = {pipe, Path} | {protocol, Protocol} | {ip, IPAddress} |
                    {progname, string()} | {interface, string()}
            Protocol = tcp | udp
            IPAddress = string() | tuple()
            Reason = posix()
            Description = string()


Try running: make

SETUID vs SUDO vs Capabilities

The procket executable needs root privileges. Either allow your user to run procket using sudo or copy procket to somewhere owned by root and make it setuid.

  • for sudo

      sudo visudo
      youruser ALL=NOPASSWD: /path/to/procket/priv/procket
  • to make it setuid

      sudo cp priv/procket /usr/local/bin
      sudo chown root:yourgroup /usr/local/bin/procket
      sudo chmod 750 /usr/local/bin/procket
      sudo chmod u+s /usr/local/bin/procket

    Use procket:open/2 and pass in the progname option:

      procket:open(22, [{progname, "/usr/local/bin/procket"}] ++ Opt).
  • use Linux capabilities: beam or the user running beam can be given whatever socket privileges are needed. For example, using file capabilities:

      setcap cap_net_raw=ep /usr/local/lib/erlang/erts-5.8.3/bin/beam.smp

    To see the capabilities:

      getcap /usr/local/lib/erlang/erts-5.8.3/bin/beam.smp

    To remove the capabilities:

      setcap -r /usr/local/lib/erlang/erts-5.8.3/bin/beam.smp


$ erl -pa ebin
Erlang R13B03 (erts-5.7.4) [source] [rq:1] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.4  (abort with ^G)
1> {ok, FD} = procket:open(53, [{protocol, udp},{type, dgram},{family, inet}]).
2> {ok, S} = gen_udp:open(53, [{fd,FD}]).
3> receive M -> M end.

$ nc -u localhost 53


To build the examples:

make examples

Simple echo server

$ erl -pa ebin
1> echo:start(53, [{protocol, tcp}, {type, stream}, {family, inet6}]).

ICMP ping

1> icmp:ping("").

Sniff the network

1> {ok, S} = procket:open(0, [{protocol, 16#0008}, {type, raw}, {family, packet}]).
2> procket:recvfrom(S, 2048).
3> {ok, S1} = gen_udp:open(0, [binary, {fd, S}, {active, false}]).
4> gen_udp:recv(S1, 2048).

Bind to one or more interfaces

1> procket:open(53, [{progname, "sudo priv/procket"},{protocol, udp},{type,dgram},{interface, "br0"}]).
2> procket:open(53, [{progname, "sudo priv/procket"},{protocol, udp},{type,dgram},{interface, "br1"}]).


procket creates a local domain socket and spawns a small setuid binary (or runs it under sudo). The executable opens a socket, drops privs and passes the file descriptor back to Erlang over the Unix socket.

procket uses libancillary for passing file descriptors between processes:


  • Docs and type specs

  • Try to re-use the Unix socket when requesting more fd's from the procket executable

  • Make a procket gen_server (gen_raw(?)).

    • Support passive and active modes.
    • Hold state for the socket, so the caller does not need to, e.g., use ifindex/2.
    • same interface for PF_PACKET and BPF


Magnus Klaar

  • support for binding a socket to an interface
  • Makefile fixes

Gregory Haskins

  • fix link-error on SUSE platforms
  • socket notifications
  • writev support

Roman Gafiyatullin

  • support running from an OTP app and compressed bundles

Kenji Rikitake

  • Added ICMPv6 support (preliminary, buggy on FreeBSD localhost I/F)

    Many localhost interfaces do not respond ICMP Echo Requests with the proper Echo Reply code.

  • Tested on FreeBSD/amd64 9.0-RELEASE alc0 interface driver