A go implementation of the STUN client (RFC 3489 and RFC 5389)



Build Status License GoDoc Go Report Card

go-stun is a STUN (RFC 3489, 5389) client implementation in golang (a.k.a. UDP hole punching).

RFC 3489: STUN - Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs)

RFC 5389: Session Traversal Utilities for NAT (STUN)

Use the Command Line Tool

Simply run these commands (if you have installed golang and set $GOPATH)

go get github.com/ccding/go-stun

or clone this repo and run these commands

go build

You will get the output like

NAT Type: Full cone NAT
External IP Family: 1
External IP:
External Port: 23009

You can use -s flag to use another STUN server, and use -v to work on verbose mode.

> ./go-stun --help
Usage of ./go-stun:
  -s string
        server address (default "stun1.l.google.com:19302")
  -v    verbose mode

Use the Library

The library github.com/ccding/go-stun/stun is extremely easy to use -- just one line of code.

import "github.com/ccding/go-stun/stun"

func main() {
	nat, host, err := stun.NewClient().Discover()

More details please go to main.go and GoDoc

  • Am I insane?

    Am I insane?


    I am testing this again, and I am hitting a strange issue, where my NAT is reported correctly as a full cone nat, but I believe it hasn't done proper testing.

    I've made a small diff just for debugging:

    @@ -125,6 +126,7 @@ func (v *packet) xorMappedAddr() *Host {
     // Retransmissions continue with intervals of 1.6s until a response is
     // received, or a total of 9 requests have been sent.
     func (v *packet) send(conn net.PacketConn, addr net.Addr) (*packet, error) {
    +       fmt.Println("send to", addr)
            timeout := 100
            for i := 0; i < 9; i++ {
                    length, err := conn.WriteTo(v.bytes(), addr)
    @@ -142,8 +144,9 @@ func (v *packet) send(conn net.PacketConn, addr net.Addr) (*packet, error) {
                            timeout *= 2
                    packetBytes := make([]byte, 1024)
    -               length, _, err = conn.ReadFrom(packetBytes)
    +               length, raddr, err := conn.ReadFrom(packetBytes)
                    if err == nil {
    +                       fmt.Println("recv", raddr)
                            return newPacketFromBytes(packetBytes[0:length])
                    if !err.(net.Error).Timeout() {

    And the verbose output is as follows:

    2016/08/05 22:46:58 Do Test1
    2016/08/05 22:46:58 Send To:
    send to
    2016/08/05 22:46:58 Received: {isNil:false}
    2016/08/05 22:46:58 Received: {changedAddr:'<nil>', identical:'false', host:''}
    2016/08/05 22:46:58 Do Test2
    2016/08/05 22:46:58 Send To:
    send to
    2016/08/05 22:46:58 Received: {isNil:false}
    Full cone NAT &{1 55777} <nil>

    Now correct me if I am wrong, but the response in Test2 came from the same address as Test1, hence there is no evidence that it is actually a full cone nat?

    I feel that it's the stun server misbehaving, yet perhaps sanity checks should be performed client side too?

    Also, I changed my router since I ran the last tests when it actually worked, so perhaps it's my router re-writing the addresses and causing this impression?

    As I seem to get the same result with multiple stun servers...

    opened by AudriusButkevicius 10
  • what is the reason

    what is the reason "Server error: response IP/port"

    stun/discover.go line 111

    if resp != nil &&
    		(resp.serverAddr.IP() == addr.IP.String() ||
    			resp.serverAddr.Port() == uint16(addr.Port)){
    // Run to this position, on behalf of what happened?
    opened by shellus 7
  • stun punching invalid a few minutes later

    stun punching invalid a few minutes later

    if I use the punchd port as a udp server ,a few minutes later, it will fail. it needs a keep alive method. the keepalive method can not cooperate with a server connection, because when keep alive called, this method will send and receive packet. generally , there only one postion for receiving packet!

    opened by nkbai 6
  • fix and check bounds reading packets

    fix and check bounds reading packets

    A lot of "slice bounds out of range" panics are occurring at https://github.com/ccding/go-stun/blob/master/stun/packet.go#L58

    https://sentry.syncthing.net/share/issue/6d20d6707bfd4880a1ed8d1205f94d1d/ https://sentry.syncthing.net/share/issue/0c228b7490c84d82a7c6357bde37028c/

    Two example bounds: [24:3] and [24:1]. Looks like the decoded uint16 length is overflowing when adding pos+4.

    Looking at the code there's a few issues:

    • The condition on the iteration is wrong: The ranges later on can exceed the packet length.
    • The header length is 20 bytes, not sure where the 24 in code comes from?
    • Converting the length to uint16 isn't ok, it might be max(uint16)+20 according to spec. I don't understand the need to do the iteration with uint16, but I kept it just in case - removing the header from the slice before taking the length.
    • The overflow: Added a condition.
    opened by imsodin 5
  • Naming of NATSymmetricUDPFirewall

    Naming of NATSymmetricUDPFirewall

    It took me a while to understand that NATSymmetricUDPFirewall actually means Symmetric UDP Firewall without any actual NAT being involved (as is also shown in the RFC and the flow chart in https://github.com/ccding/go-stun/blob/master/stun/discover.go ).

    I wonder whether this constant should be renamed / aliased to SymmetricUDPFirewall to better clarify that this is very different from NATSymmetric ?

    opened by olifre 5
  • server implementation

    server implementation

    Currently this package only contains the Client implementation, would a Server implementation be within the Scope of this package, I certainly would hope it does?

    I'm asking as I might be interested to have this working in a P2P network, where a peer would be both a client and server, so having a server implementation ready in Golang, would help a lot with that?

    I'm prepared to do the work for this, would just need to know if:

    • this is within the scope of this package;
    • this is actually something feasible;
    opened by GlenDC 4
  • go-stun can't support coturn-

    go-stun can't support coturn-

    go-stun send binding request to coturn- will fail.

    The binding request packet will drop for fingerprint. I have debug it in coturn. packet check will fail in stun_is_command_message_full_check_str.

    stun_is_command_message_full_check_str in src/client/ns_turn_msg.c
    int stun_is_command_message_full_check_str(const u08bits* buf, size_t blen, int must_check_fingerprint, int *fingerprint_present) {
            return 0;
        stun_attr_ref sar = stun_attr_get_first_by_type_str(buf, blen, STUN_ATTRIBUTE_FINGERPRINT);
        if(!sar) {
                *fingerprint_present = 0; 
            if(stun_get_method_str(buf,blen) == STUN_METHOD_BINDING) {
                return 1;
            return !must_check_fingerprint;
        if(stun_attr_get_len(sar) != 4)
            return 0;
        const u32bits* fingerprint = (const u32bits*)stun_attr_get_value(sar);
            return !must_check_fingerprint;
        u32bits crc32len = (u32bits)((((const u08bits*)fingerprint)-buf)-4);
        int ret = (*fingerprint == nswap32(ns_crc32(buf,crc32len) ^ ((u32bits)0x5354554e)));
        if(ret && fingerprint_present)
            *fingerprint_present = ret;
        return ret;

    I can use chrome send binding request to coturn- 。So, this is bug in go-stun? Thank you for reply.

    opened by lxlenovostar 3
  • Add behavior test mode.

    Add behavior test mode.

    ./go-stun -b -s stun.stunprotocol.org:3478 Mapping Behavior: EndpointIndependent Filtering Behavior: AddressAndPortDependent Normal NAT Type: Port Restricted cone NAT

    opened by kevinlemonra 2
  • Does it support ipv6?

    Does it support ipv6?

    Does it support ipv6? Although our ipv6 does not have a nat, the superior route has a firewall, and the inbound is completely blocked, and because it is a 4G network, the firewall settings cannot be changed. I am wondering whether stun can be used in ipv6.

    opened by dosgo 2
  • Configure Renovate

    Configure Renovate

    Welcome to Renovate! This is an onboarding PR to help you understand and configure settings before regular Pull Requests begin.

    :vertical_traffic_light: To activate Renovate, merge this Pull Request. To disable Renovate, simply close this Pull Request unmerged.

    Detected Package Files

    • .github/workflows/go.yml (github-actions)

    Configuration Summary

    Based on the default config's presets, Renovate will:

    • Start dependency updates only once this onboarding PR is merged
    • Separate major versions of dependencies into individual branches/PRs
    • Do not separate patch and minor upgrades into separate PRs for the same dependency
    • Upgrade to unstable versions only if the existing version is unstable
    • Raise PRs immediately (after branch is created)
    • If semantic commits detected, use semantic commit type fix for dependencies and chore for all others
    • Keep existing branches updated even when not scheduled
    • Disable automerging feature - wait for humans to merge all PRs
    • Ignore node_modules, bower_components, vendor and various test/tests directories
    • Autodetect whether to pin dependencies or maintain ranges
    • Rate limit PR creation to a maximum of two per hour
    • Limit to maximum 20 open PRs at any time
    • Group known monorepo packages together
    • Use curated list of recommended non-monorepo package groupings

    :abcd: Would you like to change the way Renovate is upgrading your dependencies? Simply edit the renovate.json in this branch with your custom config and the list of Pull Requests in the "What to Expect" section below will be updated the next time Renovate runs.

    What to Expect

    It looks like your repository dependencies are already up-to-date and no Pull Requests will be necessary right away.

    :question: Got questions? Check out Renovate's Docs, particularly the Getting Started section. If you need any further assistance then you can also request help here.

    This PR has been generated by WhiteSource Renovate. View repository job log here.

    opened by renovate[bot] 2
  • Please version go-stun

    Please version go-stun


    Could you please tag this repository?

    I am the Debian Maintainer for this project and tags would help Debian keep up with new releases/bugfixes.


    • http://semver.org/
    • http://dave.cheney.net/2016/06/24/gophers-please-tag-your-releases
    opened by aviau 2
  • Doesn't work with some servers

    Doesn't work with some servers

    For example google ones:

    stun.l.google.com:19302 stun1.l.google.com:19302 stun2.l.google.com:19302 stun3.l.google.com:19302 stun4.l.google.com:19302

    Test1 fails with "No changed address." error. Any idea what could be wrong?

    opened by AlexDevK 17
Cong Ding
Software Engineer @confluentinc | Cornell PhD | [email protected]#
Cong Ding
Fast RFC 5389 STUN implementation in go

STUN Package stun implements Session Traversal Utilities for NAT (STUN) [RFC5389] protocol and client with no external dependencies and zero allocatio

null 487 Nov 15, 2022
CoAP Client/Server implementing RFC 7252 for the Go Language

Canopus Canopus is a client/server implementation of the Constrained Application Protocol (CoAP) Updates 25.11.2016 I've added basic dTLS Support base

Zubair Hamed 150 Nov 18, 2022
Server and client implementation of the grpc go libraries to perform unary, client streaming, server streaming and full duplex RPCs from gRPC go introduction

Description This is an implementation of a gRPC client and server that provides route guidance from gRPC Basics: Go tutorial. It demonstrates how to u

Joram Wambugu 0 Nov 24, 2021
Diameter stack and Base Protocol (RFC 6733) for the Go programming language

Diameter Base Protocol Package go-diameter is an implementation of the Diameter Base Protocol RFC 6733 and a stack for the Go programming language. St

Alexandre Fiori 213 Nov 10, 2022
Package arp implements the ARP protocol, as described in RFC 826. MIT Licensed.

arp Package arp implements the ARP protocol, as described in RFC 826. MIT Licensed. Portions of this code are taken from the Go standard library. The

Matt Layher 300 Nov 10, 2022
Package dhcp6 implements a DHCPv6 server, as described in RFC 3315. MIT Licensed.

dhcp6 Package dhcp6 implements a DHCPv6 server, as described in IETF RFC 3315. MIT Licensed. At this time, the API is not stable, and may change over

Matt Layher 76 Sep 27, 2022
URI Templates (RFC 6570) implemented in Go

uritemplates -- import "github.com/jtacoma/uritemplates" Package uritemplates is a level 4 implementation of RFC 6570 (URI Template, http://tools.ietf

Joshua Tacoma 71 Jan 15, 2022
RFC 1413 compliant fake identd

RFC 1413 compliant fake identd. It is an implementation of the Ident Protocol, but it lies to the clients and always returns fake identities of queried users.

Hyeon Kim (김지현) 3 Oct 29, 2022
Rabbitio - Rabbit stream cipher package RFC 4503 for Go

rabbitio rabbitio is a rabbit stream cipher packge based on RFC 4503 for golang

Sina Ghaderi 7 Feb 8, 2022
Tailscale-client-go - A client implementation for the Tailscale HTTP API

tailscale-client-go A client implementation for the Tailscale HTTP API Example p

David Bond 0 Sep 8, 2022
A LWM2M Client and Server implementation (For Go/Golang)

Betwixt - A LWM2M Client and Server in Go Betwixt is a Lightweight M2M implementation written in Go OMA Lightweight M2M is a protocol from the Open Mo

Zubair Hamed 55 Sep 30, 2022
Golang pow implementation client <-> server over UDP and TCP protocols

Client <-> server over UDP and TCP pow protocol Denial-of-Service-attacks are a typical situation when providing services over a network. A method for

Nikita Kryuchkov 0 Jan 13, 2022
Prisma Client Go is an auto-generated and fully type-safe database client

Prisma Client Go Typesafe database access for Go Quickstart • Website • Docs • API reference • Blog • Slack • Twitter Prisma Client Go is an auto-gene

Prisma 1.3k Nov 27, 2022
KFServing Inference Client A Go re-implementation of seldon-batch-processor.

KFServing Inference Client A Go re-implementation of seldon-batch-processor. See docs to understand its usage. The main reason why we choose to re-imp

连修明 4 Jan 7, 2022
An open source Pusher server implementation compatible with Pusher client libraries written in Go

Try browsing the code on Sourcegraph! IPÊ An open source Pusher server implementation compatible with Pusher client libraries written in Go. Why I wro

Hava 1 Aug 27, 2022
iceportal-api is a Golang client implementation to interact with the REST API of iceportal.de when connected to the WiFi-Network offered in German ICE Trains.

iceportal-api is a Golang client implementation to interact with the REST API of iceportal.de when connected to the WiFi-Network offered in German ICE Trains.

Fabian Siegel 42 Aug 20, 2022
NETCONF client implementation in go.

❗ Red Hat does not provide commercial support for the content of these repos #########################################################################

Community of OpenShift Telco Experiments 13 Sep 23, 2022
The Dual-Stack Dynamic DNS client, the world's first dynamic DNS client built for IPv6.

dsddns DsDDNS is the Dual-Stack Dynamic DNS client. A dynamic DNS client keeps your DNS records in sync with the IP addresses associated with your hom

Ryan Young 15 Sep 27, 2022
Go Substrate RPC Client (GSRPC)Go Substrate RPC Client (GSRPC)

Go Substrate RPC Client (GSRPC) Substrate RPC client in Go. It provides APIs and types around Polkadot and any Substrate-based chain RPC calls. This c

Chino Chang 1 Nov 11, 2021