Giter Site home page Giter Site logo

turn's Introduction

Pion TURN
Pion TURN

A toolkit for building TURN clients and servers in Go

Pion TURN Slack Widget
GitHub Workflow Status Go Reference Coverage Status Go Report Card License: MIT


Pion TURN is a Go toolkit for building TURN servers and clients. We wrote it to solve problems we had when building RTC projects.

  • Deployable - Use modern tooling of the Go ecosystem. Stop generating config files.
  • Embeddable - Include pion/turn in your existing applications. No need to manage another service.
  • Extendable - TURN as an API so you can easily integrate with your existing monitoring and metrics.
  • Maintainable - pion/turn is simple and well documented. Designed for learning and easy debugging.
  • Portable - Quickly deploy to multiple architectures/platforms just by setting an environment variable.
  • Safe - Stability and safety is important for network services. Go provides everything we need.
  • Scalable - Create allocations and mutate state at runtime. Designed to make scaling easy.

Using

pion/turn is an API for building STUN/TURN clients and servers, not a binary you deploy then configure. It may require copying our examples and making minor modifications to fit your need, no knowledge of Go is required however. You may be able to download the pre-made binaries of our examples if you wish to get started quickly.

The advantage of this is that you don't need to deal with complicated config files, or custom APIs to modify the state of Pion TURN. After you instantiate an instance of a Pion TURN server or client you interact with it like any library. The quickest way to get started is to look at the examples or GoDoc

Examples

We try to cover most common use cases in examples. If more examples could be helpful please file an issue, we are always looking to expand and improve pion/turn to make it easier for developers.

To build any example you just need to run go build in the directory of the example you care about. It is also very easy to cross compile Go programs.

You can also see pion/turn usage in pion/ice

FAQ

Also take a look at the Pion WebRTC FAQ

Will pion/turn also act as a STUN server?

Yes.

How do I implement token-based authentication?

Replace the username with a token in the AuthHandler. The password sent by the client can be any non-empty string, as long as it matches that used by the GenerateAuthKey function.

Will WebRTC prioritize using STUN over TURN?

Yes.

RFCs

Implemented

Planned

Roadmap

The library is used as a part of our WebRTC implementation. Please refer to that roadmap to track our major milestones.

Community

Pion has an active community on the Slack.

Follow the Pion Twitter for project updates and important WebRTC news.

We are always looking to support your projects. Please reach out if you have something to build! If you need commercial support or don't want to use public methods you can contact us at [email protected]

Contributing

Check out the contributing wiki to join the group of amazing people making this project possible

License

MIT License - see LICENSE for full text

turn's People

Contributors

andrefsp avatar andylc avatar at-wat avatar backkem avatar boks1971 avatar cnderrauber avatar dongido001 avatar enobufs avatar ernado avatar hthetiot avatar hugoarregui avatar iwittkau avatar jech avatar jmattheis avatar levaitamas avatar littlelightlittlefire avatar lrezek avatar marouaneman avatar misi avatar paralax avatar paulwe avatar pionbot avatar renovate-bot avatar renovate[bot] avatar rg0now avatar sean-der avatar stv0g avatar tclift avatar ted-skydio avatar unasuke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

turn's Issues

TURN client refactor

Summary

Issues:

  • Current pion/turnc behaves as “port-restricted” NAT
  • If the other end is a symmetric NAT, ICE cannot find a valid candidate pair
  • Current pion/turnc is overly complex to fix this

Related Issues on Github

Motivation

We will try to implement a new TURN client in a way that would solve all the above problems, without having to modify pion/turnc (would be hard).
The pion/turn has its own client but it does not support TURN protocol. It's a clean place to try out the new implementation of TURN client, while leaving the pion/turnc as is to leave us "two-way door".

Describe alternatives you've considered

Modify pion/turnc .... I have tried, but it is really complex. Abstraction of channel as a net.Conn has been found fundamentally intervening in allowing ICE to detect prflx candidate which is necessary to traverse remote symmetric NAT even local end uses TURN.

Additional context

Details of issues I have found and my refactoring plan is described here

Fix missing default channel binding lifetime

Looks like I accidentally dropped it when resolving the bad merge conflict. (I dropped the old turn.go API and brought the low-level API which was hidden inside the "internal" folder which had a conflict with @songjiayang's changes.)

Relay socket should not listen on 0.0.0.0

Your environment.

  • Version: v1.2.0
  • Browser: n/a

What did you do?

This bug has been introduced since we removed ipv4.FlagDst.
Turn protocol listen ports are now using "specified" IP addresses, but relay ports have not been taken care of.

What did you expect?

Obviously, if listen addr is 0.0.0.0, permission search would fail because the permission hash is based on "specified" (non-any-addr) address.

What happened?

Permission check was always failing because the IP address did not match the incoming packets source IP.

Fixes are incoming!

Malformed packet crashes server

Your environment.

panic: runtime error: index out of range

goroutine 1 [running]:
encoding/binary.bigEndian.Uint16(...)
        /usr/local/go-d2c7dec183f0da628abf16848e9e92987feebe32/src/encoding/binary/binary.go:100
github.com/pions/pkg/stun.getChannelLength(...)
        /go/src/github.com/pions/pkg/stun/channel_data.go:40
github.com/pions/pkg/stun.NewChannelData(0xc000012600, 0x2, 0x5dc, 0x1, 0x0, 0x0)
        /go/src/github.com/pions/pkg/stun/channel_data.go:23 +0x161
github.com/pions/turn/internal/server.(*Server).handleUDPPacket(0xc000056100, 0xc00000c1c0, 0xc00000c1e0, 0xc000012600, 0x5dc, 0x5dc, 0x2, 0xc00006c870, 0x0)
        /go/src/github.com/pions/turn/internal/server/server.go:76 +0xc0
github.com/pions/turn/internal/server.(*Server).Listen(0xc000056100, 0x5670ad, 0x7, 0xd96, 0x5dc, 0x5dc)
        /go/src/github.com/pions/turn/internal/server/server.go:65 +0x2e3
github.com/pions/turn.Start(0x582220, 0x6506e8, 0xc00001a0e6, 0x11, 0xd96)
        /go/src/github.com/pions/turn/turn.go:24 +0x178
main.main()
        /go/src/github.com/pions/turn/cmd/simple-turn/main.go:48 +0x2ec

What did you do?

I was testing if the port is opened and crashed the TURN server. Oops. Very easy to repro

Start the server, in a different shell run:

echo a | nc -u localhost 3478

What did you expect?

Server gracefully handling malformed packets.

What happened?

Server crashed, see stacktrace above.

build error

simple-turn doesn't compile (with commit eeda63b):

% go version                                    
go version go1.11.5 linux/amd64
% cd ~/src/github.com/pions/turn/cmd/simple-turn
% go build
# github.com/pions/turn/internal/client
../../internal/client/stun.go:34:26: cannot use conn (type *ipv4.PacketConn) as type net.PacketConn in argument to stun.BuildAndSend:
	*ipv4.PacketConn does not implement net.PacketConn (wrong type for ReadFrom method)
		have ReadFrom([]byte) (int, *ipv4.ControlMessage, net.Addr, error)
		want ReadFrom([]byte) (int, net.Addr, error)
# github.com/pions/turn/internal/allocation
../../internal/allocation/allocation.go:206:32: cannot use a.TurnSocket (type *ipv4.PacketConn) as type net.PacketConn in argument to stun.BuildAndSend:
	*ipv4.PacketConn does not implement net.PacketConn (wrong type for ReadFrom method)
		have ReadFrom([]byte) (int, *ipv4.ControlMessage, net.Addr, error)
		want ReadFrom([]byte) (int, net.Addr, error)

I ran go get -u golang.org/x/net/... to make sure I have the latest version of net/ipv4. The build still fails for simple-turn.

Performance Improvements

Any contributions around performance improvements are welcome! The server wasn't written with performance in mind (most attention was on RFC adherence and code quality)

docker image pushed to docker hub?

$ docker pull pions/turn
Using default tag: latest
Error response from daemon: pull access denied for pions/turn, repository does not exist or may require 'docker login'
$ docker search pions/turn
NAME                                  DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
bprodoehl/turnserver                                                                  13                                      [OK]
silverpeas                            Silverpeas is a turnkey and open-source Coll…   8                   [OK]
turnkeylinux/openldap-13.0            TurnKey OpenLDAP - Open Source LDAP             8
zolochevska/turn-server               A Docker container with the Coturn TURN serv…   7                                       [OK]
spreed/turnserver                     TURN server for WebRTC usage suitable for Sp…   7                                       [OK]
turnkeylinux/core-13.0                TurnKey Core - Common Base for All Appliances   5
turnkeylinux/observium-14.1           TurnKey Observium - Network Management and M…   5
turnkeylinux/lamp-13.0                TurnKey LAMP Stack - Web Stack (MySQL)          4
turnkeylinux/elgg-13.0                TurnKey Elgg - Social Networking Engine         3
turnkeylinux/openvpn-14.1             TurnKey OpenVPN - Open Source VPN solution      3
turnkeylinux/domain-controller-14.1   TurnKey Domain Controller - Drop-in PDC repl…   3
turnkeylinux/redmine-13.0             TurnKey Redmine - Integrated SCM & Project M…   2
turnkeylinux/fileserver-14.1          TurnKey File Server - Simple Network Attache…   2
cboulanger/turnkeylinux-lamp          A Turnkeylinux LAMP Stack                       1                                       [OK]
turniere/turniere-website             The Website turnie.re                           1
zealcomm/turnserver                                                                   1
turnkeylinux/sugarcrm-13.0            TurnKey SugarCRM - Business & Social CRM Sof…   1
turnkeylinux/openldap-14.1            TurnKey OpenLDAP - Open Source Directory Ser…   1
turnkeylinux/oscommerce-14.2                                                          0
turnerdraco/drupal_tests              Images for Turner Drupal tests                  0
turnitin/jenkins                                                                      0
turnkeylinux/core-14.0                TurnKey Core - Common Base for All Appliances   0
steppechange/turn                                                                     0
lenart/heketi-turnkey                 Backing image for the heketi-turnkey deploym…   0                                       [OK]
turnkeylinux/django-14.1              TurnKey Django - High-level Python Web Frame…   0

Allocation refresh with zero lifetime not deleted as expected

Your environment.

  • Version: v1.3.3 -38ac12
  • Browser: n/a

What did you do?

Refresh allocation with 0 second lifetime

What did you expect?

The allocation doesn't remove from the manager as expected.

What happened?

Not removed, this because when we use 0 fresh lifetime, the old lifetimer only stop rather firing at once, related code is allocation.go#L165.

How to get peer's transport address

assume that We have 4 entities:
a). TURN Server (T): listening on public IP
b). TURN Client (C): somebody behind NAT that wants to connect other peer
c). Peer (P): somebody behind NAT that wants to talk with C
d). Signaling Server(S): intermediate server which helps connection setup between C and P

The process is like follows:

  1. C goes to T and asks for IP:PORT
    2). T allocates IP:PORT. It is called RELAYED ADDRESS. All data received on that address will be sent back to C. Also, C can use TURN to send data from that address to allowed peers.
    3). Now, C sends to P its RELAYED ADDRESS via S
    4). P get its transport address between P and RELAYED ADDRESS
    5). P send its transport address to C via S
    6). C create permission of P's transport address

The issue happens in #4 in case of Symmetric NAT that P should send BindRequest to RELAYED ADDRESS, but rfc5766 and pion/turn's implementation explicitly says that only UDP datagram allowed between T and P, how does it work?

Thanks in advance

[WIP] Rename 'cmd' folder to 'examples'

The pion/turn is a library, not the application, as @Sean-Der intended. We should move simple-turn and client applications into 'examples' folder.

Also, I believe we should consider removing client API (and cmd/client also), and use pion/turnc instead.

Support of external IP address mapping

Summary

When you want to host TURN server on AWS EC2 for instance, the instance can have a private IP address, but not public address directly. It allows us to have an associated public IP address (or Elastic IP, etc, there will be a NAT in betwee), but TURN server does not know about the public IP address at all. Since it is TURN server's responsibility to report the public IP address to the TURN client, there need to be a way to tell the associated public IP address to the TURN server.

Motivation

To make pion/turn available for real use cases.

Describe alternatives you've considered

Tell the external IP address via:

  1. command line option
  2. environment variable

Additional context

coturn, for instance, have -X option for this purpose.

Failed to handle ALLOCATE-REQUEST

Hi, Thanks for your awesome code.

I have a problem.
I've followed these commands to run the server

$ wget -q https://github.com/pions/turn/releases/download/1.0.3/simple-turn-linux-amd64
$ chmod +x simple-turn-linux-amd64
$ export USERS='user=password nariman=nariman'
$ export REALM=myDomain.com
$ export UDP_PORT=3478
$ ./simple-turn-linux-amd64

And I tried to check it out with this tool
photo_2019-03-06_13-17-59

The terminal showing me this error

Failed to handle ALLOCATE-REQUEST from 69.175.34.181:61666: Relay already allocated for 5-TUPLE
Failed to handle ALLOCATE-REQUEST from 69.175.34.181:61668: Relay already allocated for 5-TUPLE

I didn't find any way to solve this.
I'm running this code on Google Cloud - Ubuntu 16.

Packet unhandled

getting this error in the log "Packet unhandled in relay src "

Can any one help me why is this coming.

its in nohup.out

Off-the-shelf solution

We currently provide a binary release where you can configure the port & users with environment variables. This is rather limited. We should look into supporting multiple ways of configuration and authentication. E.g.: multiple off-the-shelf version of AuthenticateRequest. It's not entirely clear yet how to best do this. It's probably infeasible to support any kind of configuration and authentication source imaginable. Maybe there is a good balance.

One thing to consider is that this will probably introduce additional external dependencies. This should definitely be avoided in this repo since it will likely become a dependency of pions/webrtc at some point. Therefore, one thing to consider is creating a pions/turn-server repo where we build out the more fully featured off-the-shelf server.

Alternatives

  • Document that this is not our focus and more clearly show how to build your own solution.

Additional context

This point has come up a couple times now:

Migrate STUN

We moved the stun package from pkg/stun to stun. This change has to be reflected in this library.

Fix replying to ChannelBindRequest with BindingSuccess

Your environment.

What did you do?

Running the ice test in topic_vnet branch

PIONS_LOG_TRACE=all go test -v -run TestConnectivityVNet/Symmetric_NATs

What did you expect?

ChannelBindRequest completes successfully.

What happened?

I am seeing this error:

Failed to Create ChannelBind for udp4:28.1.1.1: unexpected response type Binding success response

Support hairpinning routing with TURN server

Summary

I deployed coturn server on AWS EC2, using -X option to assign a public (elastic) IP address so that allocated relayed transport address is routable.

If I use ICETransportPolicyRelay (use relay only), two pion nodes wouldn't connect with each other. The reason is, and I am pretty sure, the 1:1 private/public port mapper AWS provides (configured via security group) does not route packets between the ports on the same public IP address - so called, the hairpinning routing, is not supported.

It would be great if pion/turn server support, in addition to #56, this hairpinning routing (the green line below) which coturn does not even offer. (I reviewed its config 100 times...)

Screen Shot 2019-07-17 at 11 19 45 PM

Motivation

I believe, as long as UDP get through your local NAT/Firewall, then a relay-to-relay candidate wouldn't be necessary in most cases. Also, if many TURN servers are deployed, then the chances of two endpoints using the same instance of TURN server would be low.

But, if:

  • UDP is blocked by firewall (or only TURN server is reachable from the endpoint)
  • Using a small number of TURN servers are used (or temporarily scaled in per low traffic)

Support of the hairpinning behavior would be crucial.
(also, support of it is not expensive)

Describe alternatives you've considered

Add two relay candidates, maybe?

As we only support UDP right now. This is a low priority, I'd say.

Too many open files bug

After running the server for a day and getting a regular influx of users, I was unable to use the TURN server and got many of these errors in the console:

2018/12/07 17:32:57 Failed to handle ALLOCATE-REQUEST from x.x.x.x:37291: listen udp4 0.0.0.0:0: socket: too many open files

TURN server should return 420 (Unknown attribute) when it sees unexpected attribute

I noticed that when a request contained Requested-Transport attribute in CreatePermission, RefreshRequest or ChannelBind request, the TURN server never complains it and handles it as if it was no there.

The coturn however, returns 420 (Unknown Attribute) in the above cases.

Our TURN client is being tested with its own TURN server, it would be great to generate errors when the server sees unexpected situations.

Fix build error (nil pointer dereference)

Your environment.

  • Version: v1.3.0
  • Browser: n/a

What did you do?

CI reported build error (log shown below)

What did you expect?

Build and tests to pass

What happened?

=== RUN   TestServer/simple
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x68771e]
goroutine 32 [running]:
time.(*Timer).Stop(...)
	/home/travis/.gimme/versions/go1.12.7.linux.amd64/src/time/sleep.go:74
github.com/pion/turn/internal/client.(*Transaction).StopRtxTimer(0xc0001dc070)
	/home/travis/gopath/src/github.com/pion/turn/internal/client/transaction.go:75 +0xbe
github.com/pion/turn.(*Client).handleSTUNMessage(0xc0001b0240, 0xc0001fc000, 0x28, 0xffff, 0x998060, 0xc00020e000, 0xc00020e000, 0x0)
	/home/travis/gopath/src/github.com/pion/turn/client.go:474 +0x99c
github.com/pion/turn.(*Client).HandleInbound(0xc0001b0240, 0xc0001fc000, 0x28, 0xffff, 0x998060, 0xc00020e000, 0xc00020e000, 0x0, 0x0)
	/home/travis/gopath/src/github.com/pion/turn/client.go:400 +0x63c
github.com/pion/turn.(*Client).Listen.func1(0xc0001b0240)
	/home/travis/gopath/src/github.com/pion/turn/client.go:173 +0x18d
created by github.com/pion/turn.(*Client).Listen
	/home/travis/gopath/src/github.com/pion/turn/client.go:164 +0x1e1
FAIL	github.com/pion/turn	1.390s

This never happens on my PC, but I found a typo in the code. The nil check was done against a wrong variable:

// StopRtxTimer stop the transaction timer
func (t *Transaction) StopRtxTimer() {
	t.mutex.Lock()
	defer t.mutex.Unlock()

	if t != nil { // <----------------- :(  this should be t.time
		t.timer.Stop()
	}
}

Add TCP support

Currently we only support UDP clients

If this blocks you from using pion-turn please comment, and we can escalate

Finish logging design

Since we are embedded we should probably allow people to bring their own logger (and default to zerolog to the examples?)

TURN server should behave 'address-restricted-filtering'

Your environment.

  • Version: v1.2.0
  • Browser: n/a

What did you do?

I wrote a test: https://github.com/pion/ice/blob/topic-vnet/connectivity_vnet_test.go
in which there are symmetric NATs on both ends, if one end did not have TURN server URL (but has STUN server URL), the connection fails!

What did you expect?

srflx-relay pair should succeed, when both ends have a symmetric NAT, and only one end have TURN server URL.

What happened?

Connection fails.
Looking at this spec, TURN server (Permission) should do address-restricted filtering

To ease concerns amongst enterprise IT administrators that TURN could be used to bypass corporate firewall security, TURN includes the notion of permissions. TURN permissions mimic the address-restricted filtering mechanism of NATs that comply with [RFC4787].

But looking at the current implementation of TURN permission, the fingerprint includes port number... We should exclude the port number from the fingerprint and its comparison with the srcAddr.

@songjiayang Can you confirm my above observation?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.