need clarification on sending to remote actors through NAT

724 views
Skip to first unread message

Scott Clasen

unread,
Mar 29, 2012, 1:05:10 PM3/29/12
to akka...@googlegroups.com
Hi-

  There have been a few posts that show people having trouble with Remoting and NAT, and I just want to clarify whether its actually possible when one is living under the constraint of having to use NAT to send messages to remote actors, and if so, what is the proper configuration to do so

If I am getting errors like this

ERROR] [03/29/2012 16:59:15.706] [theSystem-11] [NettyRemoteTransport(null)] dropping message ... for non-local recipient akka://theSystem@publicHost:publicPort/user/some/actor at akka://theS...@0.0.0.0:32058 local is akka://theS...@0.0.0.0:32058

How do I configure the "reciever" side such that it listens on 0.0.0.0:32058 but accepts messages for publicHost:publicPort?

Thanks
SC


Roland Kuhn

unread,
Mar 29, 2012, 2:19:59 PM3/29/12
to akka...@googlegroups.com
Hi Scott,

That is currently not possible (it is not unthinkable, though, to add such a configuration option). The problem with NAT in general is the one-way reachability, and we allow for that by re-using incoming connections for outgoing messages; as long as you just use that, everything should be fine. But make sure to reestablish the server connection from the client when it fails (can be done by sending some message).

Regards,

Roland Kuhn
Typesafe – The software stack for applications that scale.
twitter: @rolandkuhn


Scott Clasen

unread,
Mar 29, 2012, 2:45:40 PM3/29/12
to akka...@googlegroups.com
Hi Roland-

 So I have a workaround that seems to be working. Any reason that you would caution me not to do such a thing?  Here are the important parts, recieveMessage is cut and pasted from NettyRemoteSupport and I add one more case clause, noted below...

class NATFriendlyNettyRemoteSupport ... extends NettyRemoteSuport ...

override def receiveMessage(remoteMessage: RemoteMessage)....

case r: RemoteRef ⇒
        if (provider.remoteSettings.LogReceive) log.debug("received remote-destined message {}", remoteMessage)
        remoteMessage.originalReceiver match {
          case AddressFromURIString(address) if address == provider.transport.address ⇒
            // if it was originally addressed to us but is in fact remote from our point of view (i.e. remote-deployed)
            r.!(remoteMessage.payload)(remoteMessage.sender)
          //////////NEW STUFF STARTS HERE
          case AddressFromURIString(address) ⇒
            val localPath = remoteMessage.recipient.path.toString.split("/user/", 2)(1)
            import collection.JavaConverters._
            val path = userPath.descendant(localPath.split("/").toIterable.asJava)
            system.actorFor(path).!(remoteMessage.payload)(remoteMessage.sender)
          ////////////NEW STUFF ENDS HERE
          case r =>
            log.error("dropping message {} for non-local recipient {} at {} local is {}", remoteMessage.payload, r, address, provider.transport.address)
        }


Thanks!
SC

Scott Clasen

unread,
Mar 29, 2012, 2:48:56 PM3/29/12
to akka...@googlegroups.com
Oops, Should read NettyRemoteTransport, not NettyRemoteSupport  


On Thursday, March 29, 2012 11:45:40 AM UTC-7, Scott Clasen wrote:
Hi Roland-

 So I have a workaround that seems to be working. Any reason that you would caution me not to do such a thing?  Here are the important parts, recieveMessage is cut and pasted from NettyRemoteTransport and I add one more case clause, noted below...

class NATFriendlyNettyRemoteTransport ... extends NettyRemoteTransport ...

Roland Kuhn

unread,
Mar 29, 2012, 3:23:31 PM3/29/12
to akka...@googlegroups.com
Hi Scott,

it’s getting late, so don’t trust me when I say that I currently don’t see a reason why this should blow up horribly ;-) Seriously, though, I have put in this strict verification because I thought that if you setup remote communication between parties, you should better know who is talking to whom, and you’ll probably want to know when it looks fishy. And for sure you don’t want to blindly send off the message across the network to some unknown destination (which you side-step by always looking up locally). So, after this warning I can dig into the treasure box:

case ActorPathExtractor(addr, elements) => system.actorFor(elements).tell(remoteMessage.payload, remoteMessage.sender)

You can also insert a guard like “if setOfAcceptableAddrs contains add” …

Regards,

Roland

--
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To view this discussion on the web visit https://groups.google.com/d/msg/akka-user/-/8xnMYkvyTfoJ.
To post to this group, send email to akka...@googlegroups.com.
To unsubscribe from this group, send email to akka-user+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.

Scott Clasen

unread,
Mar 29, 2012, 3:27:13 PM3/29/12
to akka...@googlegroups.com
Nice, I was sure there is a cleaner way.  I will be adding the guard condition too

Thanks again!
To unsubscribe from this group, send email to akka-user+unsubscribe@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.

G J

unread,
Apr 24, 2012, 4:42:20 PM4/24/12
to Akka User List
Hi Roland,

I get the same error communicating to a machine that is NAT'd, and
tried to follow your advice (reusing incoming connections for outgoing
messages) without any luck:

I have a ping program that is sending messages to a server, and the
server emits the "NettyRemoteTransport(null) dropping message for non-
local recipient <path> at <path> local is <path>".

I added the following line to the server configuration:

remote.netty.use-passive-connections = on

which should not be necessary as it is enabled by default.

In more detail:
client: send to [akka://X@<remote facing IP>:2553>
application.conf:
hostname = <nat'd address>
port = 2554

server:
application.conf:
hostname = <nat'd address>
port = 2553
use-passive-connection = on

Thanks for any help.






On Mar 29, 2:19 pm, Roland Kuhn <goo...@rkuhn.info> wrote:
> Hi Scott,
>
> On Mar 29, 2012, at 19:05 , Scott Clasen wrote:
>
> >   There have been a few posts that show people having trouble with Remoting and NAT, and I just want to clarify whether its actually possible when one is living under the constraint of having to use NAT to send messages to remote actors, and if so, what is the proper configuration to do so
>
> > If I am getting errors like this
>
> > ERROR] [03/29/2012 16:59:15.706] [theSystem-11] [NettyRemoteTransport(null)] dropping message ... for non-local recipient akka://theSystem@publicHost:publicPort/user/some/actor at akka://theSys...@0.0.0.0:32058 local is akka://theSys...@0.0.0.0:32058

G J

unread,
Apr 24, 2012, 9:24:50 PM4/24/12
to Akka User List
Scott,

Thanks for NATFriendlyNettyRemoteSupport class!! A preliminary test
showed that it worked great!

Do you have an opinion on using VPN solutions in these situations?

Technically it would mimick a LAN with no address translation, so
everything should work. Unfortunately, it opens up a can of worms as
well. A VPN client will have to be running, adding more layers,
possible fairly points, and complexity. NATFriendlyNettyRemoteSupport
is integrated and appears simple enough.

Thanks.

Best Regards.
-------
On Mar 29, 2:45 pm, Scott Clasen <scott.cla...@gmail.com> wrote:
> Hi Roland-
>
> So I have a workaround that seems to be working. Any reason that you would
> caution me not to do such a thing? Here are the important parts,
> recieveMessage is cut and pasted from NettyRemoteSupport and I add one more
> case clause, noted below...
>
> class NATFriendlyNettyRemoteSupport ... extends NettyRemoteSuport ...
>
> override def receiveMessage(remoteMessage: RemoteMessage)....
>
> case r: RemoteRef =>
> if (provider.remoteSettings.LogReceive) log.debug("received
> remote-destined message {}", remoteMessage)
> remoteMessage.originalReceiver match {
> case AddressFromURIString(address) if address ==
> provider.transport.address =>
> // if it was originally addressed to us but is in fact remote
> from our point of view (i.e. remote-deployed)
> r.!(remoteMessage.payload)(remoteMessage.sender)
> //////////NEW STUFF STARTS HERE
> case AddressFromURIString(address) =>
> val localPath =
> remoteMessage.recipient.path.toString.split("/user/", 2)(1)
> import collection.JavaConverters._
> val path =
> userPath.descendant(localPath.split("/").toIterable.asJava)
>
> system.actorFor(path).!(remoteMessage.payload)(remoteMessage.sender)
> ////////////NEW STUFF ENDS HERE
> case r =>
> log.error("dropping message {} for non-local recipient {} at {}
> local is {}", remoteMessage.payload, r, address, provider.transport.address)
> }
>
> Thanks!
> SC
>
>
>
>
>
>
>
> On Thursday, March 29, 2012 11:19:59 AM UTC-7, rkuhn wrote:
>
> > Hi Scott,
>
> > On Mar 29, 2012, at 19:05 , Scott Clasen wrote:
>
> > There have been a few posts that show people having trouble with
> > Remoting and NAT, and I just want to clarify whether its actually possible
> > when one is living under the constraint of having to use NAT to send
> > messages to remote actors, and if so, what is the proper configuration to
> > do so
>
> > If I am getting errors like this
>
> > ERROR] [03/29/2012 16:59:15.706] [theSystem-11]
> > [NettyRemoteTransport(null)] dropping message ... for non-local recipient
> > akka://theSystem@publicHost:publicPort/user/some/actor at
> > akka://theSys...@0.0.0.0:32058 local is akka://theSys...@0.0.0.0:32058
>
> > How do I configure the "reciever" side such that it listens on
> > 0.0.0.0:32058 but accepts messages for publicHost:publicPort?
>
> > That is currently not possible (it is not unthinkable, though, to add such
> > a configuration option). The problem with NAT in general is the one-way
> > reachability, and we allow for that by re-using incoming connections for
> > outgoing messages; as long as you just use that, everything should be fine.
> > But make sure to reestablish the server connection from the client when it
> > fails (can be done by sending some message).
>
> > Regards,
>
> > Roland Kuhn
> > Typesafe <http://typesafe.com/> - The software stack for applications
> > that scale.
> > twitter: @rolandkuhn <http://twitter.com/#!/rolandkuhn>

Roland Kuhn

unread,
Apr 25, 2012, 3:06:36 AM4/25/12
to akka...@googlegroups.com

On Apr 25, 2012, at 03:24 , G J wrote:

> Scott,
>
> Thanks for NATFriendlyNettyRemoteSupport class!! A preliminary test
> showed that it worked great!
>
> Do you have an opinion on using VPN solutions in these situations?
>
My opinion would be to properly setup networking according to the requirements you have, which might mean buying routers which support VPN and connect subnets in a secure way. There is no need for VPN clients running anywhere in that scenario. If you have mobile devices which you need to connect securely, the options are rather limited, and above a certain classification there is no legal solution anyway.

Another piece of opinion is that the security layer should be transparent, i.e. no NAT (apart from the size problem vs. 32bit, there is really no reason at all for using this technique). We have a ticket for integrating SSL support into the RemoteTransport, which would take care of those parts of the problem left out int the paragraph above as far as I can see.

That said, Akka remoting has been built on the assumption that it is to be used for scaling out within a cluster, i.e. in a trusted environment. It is nice to see that it can be used for other things as well, and we will eventually tackle those propertly, but the foremost priority now is to get the core functionality in place. NATFriendlyNettyRemoteSupport is a temporary work-around on this road, so thanks to Scott for taking the pressure off a little bit :-)


Regards,

Roland
> --
> You received this message because you are subscribed to the Google Groups "Akka User List" group.
> To post to this group, send email to akka...@googlegroups.com.
> To unsubscribe from this group, send email to akka-user+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.
>

Roland Kuhn
Typesafe – The software stack for applications that scale.
twitter: @rolandkuhn


G J

unread,
Apr 25, 2012, 7:55:37 AM4/25/12
to Akka User List
Roland,

Thanks for sharing that. It is well thought out.

We hope to eventually have two security appliances at both ends -
office, and data center; and, a lot of these ugly issues will go away.
Right now we have a security appliance at the data center, and our
office is 'home' locations. Thus the work-around is godsent. We do a
straight ssh into the NAT'd server.

Best Regards.
> > For more options, visit this group athttp://groups.google.com/group/akka-user?hl=en.

Guillaume Simard

unread,
May 22, 2012, 2:56:17 PM5/22/12
to akka...@googlegroups.com
Hello Roland,

I just thought I could add my voice to this thread to show there is interest in Akka remoting over the untrusted internet.

First of all thanks to Scott and yourself for this simple and effective NAT-problem workaround: I've added the NATFriendlyNettyRemoteTransport class to my application and it works like a charm.

I'm using Akka in a game where there is both server-server communication and client-server communication. Server-server communication is bound to a "private" LAN (the Amazon EC2 cloud), but client-server communication can happen from anywhere on the internet and should not be filtered by default if real IPs (WAN-side) do not match declared IPs (LAN-side).

Furthermore, I think I've read that should it happen that two clients with the same IPs connect at the same time (which is highly probable as personnal LANs use the 192.168.{0,1}.x subnets) Akka will by default drop one of the two. This, it seems to me, belongs to the same class of problem as this thread is discussing about. Maybe there should be some design decision to solve both issues ?

Regards,
Guillaume Simard
To unsubscribe from this group, send email to akka-user+unsubscribe@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.

√iktor Ҡlang

unread,
May 22, 2012, 3:23:42 PM5/22/12
to akka...@googlegroups.com
Hi Guillaume!

On Tue, May 22, 2012 at 8:56 PM, Guillaume Simard <gsi...@gmail.com> wrote:
Hello Roland,

I just thought I could add my voice to this thread to show there is interest in Akka remoting over the untrusted internet.

That awesome to hear! :-)
 

First of all thanks to Scott and yourself for this simple and effective NAT-problem workaround: I've added the NATFriendlyNettyRemoteTransport class to my application and it works like a charm.

Great to hear that it works well for you, I'm not fully convinced that it's 100% there though since the place of the patch is just local and there are likle more places where the same consideration needs to be made.
 

I'm using Akka in a game where there is both server-server communication and client-server communication. Server-server communication is bound to a "private" LAN (the Amazon EC2 cloud), but client-server communication can happen from anywhere on the internet and should not be filtered by default if real IPs (WAN-side) do not match declared IPs (LAN-side).

There is a ticket about this, feel free to contribute: http://www.assembla.com/spaces/akka/tickets/1552
 

Furthermore, I think I've read that should it happen that two clients with the same IPs connect at the same time (which is highly probable as personnal LANs use the 192.168.{0,1}.x subnets) Akka will by default drop one of the two. This, it seems to me, belongs to the same class of problem as this thread is discussing about. Maybe there should be some design decision to solve both issues ?

Both IP and port is considered, so there's only a clash in rare circumstances. (because I assume you're binding to a random port, right?)

Cheers,
 
To view this discussion on the web visit https://groups.google.com/d/msg/akka-user/-/63WmKphMLgAJ.

To post to this group, send email to akka...@googlegroups.com.
To unsubscribe from this group, send email to akka-user+...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.



--
Viktor Klang

Akka Tech Lead
Typesafe - The software stack for applications that scale

Twitter: @viktorklang

Guillaume Simard

unread,
May 22, 2012, 3:43:29 PM5/22/12
to akka...@googlegroups.com
This is correct: if using a random port (0) the clash would be rare,
but that would depend on the number of clients out there.

Whenever the number of clients would get in the hundreds, clashes
would be more frequent (many out there have IP 192.168.1.100).

Also, a clash could turn out to be entirely unacceptable in some applications.

I'm not sure how I'm going to solve this problem right now. Perhaps a
third field, the UID, could be generated randomly by the client and
used to identify the transaction more uniquely. Of course, this is not
secure (SSL would be required for security), but at least it could
avoid clashes.

Guillaume
>>> akka-user+...@googlegroups.com.
>>> For more options, visit this group at
>>> http://groups.google.com/group/akka-user?hl=en.
>>>
>>>
>>> Roland Kuhn
>>> Typesafe – The software stack for applications that scale.
>>> twitter: @rolandkuhn
>>>
>>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Akka User List" group.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msg/akka-user/-/63WmKphMLgAJ.
>>
>> To post to this group, send email to akka...@googlegroups.com.
>> To unsubscribe from this group, send email to
>> akka-user+...@googlegroups.com.
>> For more options, visit this group at
>> http://groups.google.com/group/akka-user?hl=en.
>
>
>
>
> --
> Viktor Klang
>
> Akka Tech Lead
> Typesafe - The software stack for applications that scale
>
> Twitter: @viktorklang
>
> --
> You received this message because you are subscribed to the Google Groups
> "Akka User List" group.
> To post to this group, send email to akka...@googlegroups.com.
> To unsubscribe from this group, send email to
> akka-user+...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/akka-user?hl=en.



--
Guillaume Simard, B.Ing., M.Sc.A.
e.   gsi...@gmail.com
t.    514-501-5707

√iktor Ҡlang

unread,
May 22, 2012, 4:00:52 PM5/22/12
to akka...@googlegroups.com
On Tue, May 22, 2012 at 9:43 PM, Guillaume Simard <gsi...@gmail.com> wrote:
This is correct: if using a random port (0) the clash would be rare,
but that would depend on the number of clients out there.

Whenever the number of clients would get in the hundreds, clashes
would be more frequent (many out there have IP 192.168.1.100).

Also, a clash could turn out to be entirely unacceptable in some applications.

I'm not sure how I'm going to solve this problem right now. Perhaps a
third field, the UID, could be generated randomly by the client and
used to identify the transaction more uniquely. Of course, this is not
secure (SSL would be required for security), but at least it could
avoid clashes.

Looking forward to hear if you come up with something!

Cheers,

Roland Kuhn

unread,
May 22, 2012, 4:27:06 PM5/22/12
to akka...@googlegroups.com
Just sketching a bit, don’t take this as a commitment:

99% of the problem would be solved by using the peer InetSocketAddress of the inbound connection for identifying that client actor system. Then the server system would reply with a “hello” message as part of the initial handshake to tell the client this socket address, and the client would use that when serializing actor refs for that connection. This would enable replies to reach the right client, who then would know to accept that Address (since it is the one it will be putting in itself). The problem remains, of course, that if such a RemoteActorRef is passed from the server to some back-end actor system, that system would not be able to send to the client directly (because no TCP connection exists and none can be established). That could potentially be solved by mangling the RemoteActorRef during serialization again, re-pointing it to the local system’s address and inserting path elements which will later affect the sending through the right tunnel. There are lots of issues here, though, beginning with alternate serialization schemes (which would all consistently have to use ActorRefProvider.getExternalAddressFor()) and not ending with dropped and re-established connections to the same system and what to do with replies after such an event. Also interesting: how to treat temporarily disconnected remote systems from DeathWatch’s perspective?

When trying to implement this, more questions will arise, and my guess is that true location transparency cannot be achieved without network transparency, so if someone steps up to write this hypothetical new RemoteTransport (and possibly ActorRefProvider) that would probably not be a first-class citizen, i.e. solve a niche problem. Might be very useful nonetheless, I just don’t want to nourish hope that one day the default will be to transparently handle NAT without any drawbacks (if memory leaks were an allowed drawback, that would simplify things a lot ;-) ).

Regards,

Roland
Reply all
Reply to author
Forward
0 new messages