Socket option FREEBIND

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Socket option FREEBIND

Michael L Martin
Hi all,

Is there a way to specify the FREEBIND option when opening a socket? I
don't see any reference to it in the documentation.


Thanks,

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Socket option FREEBIND

Guilherme Andrade
I believe you can use raw socket options[1] for that, but it won't be portable.

[1]: http://erlang.org/doc/man/inet.html#setopts-2 - {raw, Protocol, OptionNum, ValueBin}

On 16 October 2017 at 15:09, Michael L Martin <[hidden email]> wrote:
Hi all,

Is there a way to specify the FREEBIND option when opening a socket? I don't see any reference to it in the documentation.


Thanks,

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions



--
Guilherme

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Socket option FREEBIND

Andreas Schultz
----- On Oct 16, 2017, at 7:18 PM, Guilherme Andrade <[hidden email]> wrote:
I believe you can use raw socket options[1] for that, but it won't be portable.
IP_FREEBIND is Linux only. FreeBSD has IP(V6)_BINDANY, which is similar but not identical. Windows apparently has nothing alike. Don't know about the other OS's.

Andreas


[1]: http://erlang.org/doc/man/inet.html#setopts-2 - {raw, Protocol, OptionNum, ValueBin}

On 16 October 2017 at 15:09, Michael L Martin <[hidden email]> wrote:
Hi all,

Is there a way to specify the FREEBIND option when opening a socket? I don't see any reference to it in the documentation.


Thanks,

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions



--
Guilherme

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Socket option FREEBIND

Michael L Martin
In reply to this post by Guilherme Andrade

Raw socket options looks like it should be the answer, but I'm not getting good results:

iex([hidden email])28> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 63}}])

{:ok, #Port<0.12110>}

iex([hidden email])29> :inet.getopts(s, [{:raw, 6, 15, 32}])

{:ok, []}    <== option not set?

iex([hidden email])29> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 64}}])

** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}


It appears that the IP_FREEBIND option is simply not set. If I use IP_TRANSPARENT instead:

iex([hidden email])35> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 6, 19, <<1>>}, {:ip, {10, 138, 69, 63}}])

{:ok, #Port<0.12113>}

iex([hidden email])34> :inet.getopts(s, [{:raw, 6, 19, 32}])

{:ok, [{:raw, 6, 19, <<0, 0, 0, 0>>}]}


In this case, the raw option 19 (IP_TRANSPARENT) is set, but to false rather than true. I believe this is because the beam file needs root or CAP_NET_ADMIN.

Any thoughts?




On 2017-10-16 01:18 PM, Guilherme Andrade wrote:
I believe you can use raw socket options[1] for that, but it won't be portable.

[1]: http://erlang.org/doc/man/inet.html#setopts-2 - {raw, Protocol, OptionNum, ValueBin}

On 16 October 2017 at 15:09, Michael L Martin <[hidden email]> wrote:
Hi all,

Is there a way to specify the FREEBIND option when opening a socket? I don't see any reference to it in the documentation.


Thanks,

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions



--
Guilherme


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Socket option FREEBIND

Andreas Schultz
Hi,

----- On Oct 20, 2017, at 5:10 PM, Michael L Martin <[hidden email]> wrote:

Raw socket options looks like it should be the answer, but I'm not getting good results:

iex([hidden email])28> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 63}}])

{:ok, #Port<0.12110>}

iex([hidden email])29> :inet.getopts(s, [{:raw, 6, 15, 32}])

{:ok, []}    <== option not set?

iex([hidden email])29> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 64}}])

** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}


IP_FREEBIND on connect doesn't make sense, it's only really useful on listen sockets.

The option lets you bind to an IP address that does not yet exist on the host. That is ok for listen, but when you attempt to build an outgoing connection from that IP, then it has to be configured.

It appears that the IP_FREEBIND option is simply not set. If I use IP_TRANSPARENT instead:

iex([hidden email])35> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 6, 19, <<1>>}, {:ip, {10, 138, 69, 63}}])

{:ok, #Port<0.12113>}

iex([hidden email])34> :inet.getopts(s, [{:raw, 6, 19, 32}])

{:ok, [{:raw, 6, 19, <<0, 0, 0, 0>>}]}


IP_TRANSPARENT needs special iptables rules to work correctly and is for a very specific use case. I don't think it would be very useful for an Erlang application to use that.

In this case, the raw option 19 (IP_TRANSPARENT) is set, but to false rather than true. I believe this is because the beam file needs root or CAP_NET_ADMIN.

You need root and a specific iptables setup for it to work.

Any thoughts?


What are you attempting to achieve anyway?

Regards
Andreas




On 2017-10-16 01:18 PM, Guilherme Andrade wrote:
I believe you can use raw socket options[1] for that, but it won't be portable.

[1]: http://erlang.org/doc/man/inet.html#setopts-2 - {raw, Protocol, OptionNum, ValueBin}

On 16 October 2017 at 15:09, Michael L Martin <[hidden email]> wrote:
Hi all,

Is there a way to specify the FREEBIND option when opening a socket? I don't see any reference to it in the documentation.


Thanks,

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions



--
Guilherme


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Socket option FREEBIND

Michael L Martin

Thanks for the quick response. As for what I'm  attempting to achieve, well, I'm not really sure.

I have a customer that is adamant that we use IP_FREEBIND, so I've been poking around in :gen_tcp and :inet trying to see how to do that.

Here's what happens when I try to open a listen socket:

iex(5)> {:ok, s} = :gen_tcp.listen(8000, [{:raw, 6, 15, <<1 :: size(32)>>}, {:ip, {10, 138, 69, 63}}])
{:ok, #Port<0.1305>}
iex(6)> :inet.getopts(s, [{:raw, 6, 15, 4}])                                                         
{:ok, []}
iex(7)> :gen_tcp.close(s)
:ok
iex(8)> {:ok, s} = :gen_tcp.listen(8000, [{:raw, 6, 15, <<1 :: size(32)>>}, {:ip, {10, 138, 69, 64}}])
** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}

iex(8)>

So it looks like it's not working for listen sockets, either. Could very well be that I simply don't know what the heck I'm doing...



On 2017-10-20 12:04 PM, Andreas Schultz wrote:
Hi,

----- On Oct 20, 2017, at 5:10 PM, Michael L Martin [hidden email] wrote:

Raw socket options looks like it should be the answer, but I'm not getting good results:

iex([hidden email])28> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 63}}])

{:ok, #Port<0.12110>}

iex([hidden email])29> :inet.getopts(s, [{:raw, 6, 15, 32}])

{:ok, []}    <== option not set?

iex([hidden email])29> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 64}}])

** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}


IP_FREEBIND on connect doesn't make sense, it's only really useful on listen sockets.

The option lets you bind to an IP address that does not yet exist on the host. That is ok for listen, but when you attempt to build an outgoing connection from that IP, then it has to be configured.

It appears that the IP_FREEBIND option is simply not set. If I use IP_TRANSPARENT instead:

iex([hidden email])35> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 6, 19, <<1>>}, {:ip, {10, 138, 69, 63}}])

{:ok, #Port<0.12113>}

iex([hidden email])34> :inet.getopts(s, [{:raw, 6, 19, 32}])

{:ok, [{:raw, 6, 19, <<0, 0, 0, 0>>}]}


IP_TRANSPARENT needs special iptables rules to work correctly and is for a very specific use case. I don't think it would be very useful for an Erlang application to use that.

In this case, the raw option 19 (IP_TRANSPARENT) is set, but to false rather than true. I believe this is because the beam file needs root or CAP_NET_ADMIN.

You need root and a specific iptables setup for it to work.

Any thoughts?


What are you attempting to achieve anyway?

Regards
Andreas




On 2017-10-16 01:18 PM, Guilherme Andrade wrote:
I believe you can use raw socket options[1] for that, but it won't be portable.

[1]: http://erlang.org/doc/man/inet.html#setopts-2 - {raw, Protocol, OptionNum, ValueBin}

On 16 October 2017 at 15:09, Michael L Martin <[hidden email]> wrote:
Hi all,

Is there a way to specify the FREEBIND option when opening a socket? I don't see any reference to it in the documentation.


Thanks,

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions



--
Guilherme


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Socket option FREEBIND

Richard Jones
I'm able to make outbound connections bound to an arbitrary IP from my
range by specifying a socket option like: {raw, 0, 15, <<1>>}

note that that protocol part of {raw, ???, _, _} is 0, not 6, since
it's an IP level socket option (not tcp-level).

btw there's also a system-wide option so you don't need to specify
ip_freebind per socket:

echo 1 > /proc/sys/net/ipv6/ip_nonlocal_bind


RJ

On 20 October 2017 at 17:17, Michael L Martin <[hidden email]> wrote:

> Thanks for the quick response. As for what I'm  attempting to achieve, well,
> I'm not really sure.
>
> I have a customer that is adamant that we use IP_FREEBIND, so I've been
> poking around in :gen_tcp and :inet trying to see how to do that.
>
> Here's what happens when I try to open a listen socket:
>
> iex(5)> {:ok, s} = :gen_tcp.listen(8000, [{:raw, 6, 15, <<1 :: size(32)>>},
> {:ip, {10, 138, 69, 63}}])
> {:ok, #Port<0.1305>}
> iex(6)> :inet.getopts(s, [{:raw, 6, 15, 4}])
> {:ok, []}
> iex(7)> :gen_tcp.close(s)
> :ok
> iex(8)> {:ok, s} = :gen_tcp.listen(8000, [{:raw, 6, 15, <<1 :: size(32)>>},
> {:ip, {10, 138, 69, 64}}])
> ** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}
>
> iex(8)>
>
> So it looks like it's not working for listen sockets, either. Could very
> well be that I simply don't know what the heck I'm doing...
>
>
>
> On 2017-10-20 12:04 PM, Andreas Schultz wrote:
>
> Hi,
>
> ----- On Oct 20, 2017, at 5:10 PM, Michael L Martin <[hidden email]>
> wrote:
>
> Raw socket options looks like it should be the answer, but I'm not getting
> good results:
>
> iex(worker@10.138.69.63)28> {:ok, s} = :gen_tcp.connect('localhost', 80,
> [{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 63}}])
>
> {:ok, #Port<0.12110>}
>
> iex(worker@10.138.69.63)29> :inet.getopts(s, [{:raw, 6, 15, 32}])
>
> {:ok, []}    <== option not set?
>
> iex(worker@10.138.69.63)29> {:ok, s} = :gen_tcp.connect('localhost', 80,
> [{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 64}}])
>
> ** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}
>
>
> IP_FREEBIND on connect doesn't make sense, it's only really useful on listen
> sockets.
>
> The option lets you bind to an IP address that does not yet exist on the
> host. That is ok for listen, but when you attempt to build an outgoing
> connection from that IP, then it has to be configured.
>
> It appears that the IP_FREEBIND option is simply not set. If I use
> IP_TRANSPARENT instead:
>
> iex(worker@10.138.69.63)35> {:ok, s} = :gen_tcp.connect('localhost', 80,
> [{:raw, 6, 19, <<1>>}, {:ip, {10, 138, 69, 63}}])
>
> {:ok, #Port<0.12113>}
>
> iex(worker@10.138.69.63)34> :inet.getopts(s, [{:raw, 6, 19, 32}])
>
> {:ok, [{:raw, 6, 19, <<0, 0, 0, 0>>}]}
>
>
> IP_TRANSPARENT needs special iptables rules to work correctly and is for a
> very specific use case. I don't think it would be very useful for an Erlang
> application to use that.
>
> In this case, the raw option 19 (IP_TRANSPARENT) is set, but to false rather
> than true. I believe this is because the beam file needs root or
> CAP_NET_ADMIN.
>
> You need root and a specific iptables setup for it to work.
>
> Any thoughts?
>
>
> What are you attempting to achieve anyway?
>
> Regards
> Andreas
>
>
>
>
> On 2017-10-16 01:18 PM, Guilherme Andrade wrote:
>
> I believe you can use raw socket options[1] for that, but it won't be
> portable.
>
> [1]: http://erlang.org/doc/man/inet.html#setopts-2 - {raw, Protocol,
> OptionNum, ValueBin}
>
> On 16 October 2017 at 15:09, Michael L Martin <[hidden email]> wrote:
>>
>> Hi all,
>>
>> Is there a way to specify the FREEBIND option when opening a socket? I
>> don't see any reference to it in the documentation.
>>
>>
>> Thanks,
>>
>> _______________________________________________
>> erlang-questions mailing list
>> [hidden email]
>> http://erlang.org/mailman/listinfo/erlang-questions
>
>
>
>
> --
> Guilherme
>
>
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
>
>
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
>
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Socket option FREEBIND

Richard Jones
I should add, I do this with the AnyIP routing rule like so:

ip route add local 2604:8300:100:200b:6667:8::/96 dev lo

(i actually use dummy0 instead of "lo", ymmv)

per: https://blog.widodh.nl/2016/04/anyip-bind-a-whole-subnet-to-your-linux-machine/

also testable using socat like this:

socat -d -d TCP6:[2600:3c02::f03c:91ff:fe59:7d2e]:6667,bind=[2604:8300:100:200b:6667:8::1],setsockopt-int=0:15:1
-

this example connects to v6 freenode irc
(2600:3c02::f03c:91ff:fe59:7d2e) from an ipv6 address in the range i
set up anyip routing for.

So i can connect from that source ip (2604:8300:100:200b:6667:8::1)
but "ip addr" or "ifconfig" don't list that exact IP as being
configured.

Regards,

RJ



On 20 October 2017 at 17:33, Richard Jones <[hidden email]> wrote:

> I'm able to make outbound connections bound to an arbitrary IP from my
> range by specifying a socket option like: {raw, 0, 15, <<1>>}
>
> note that that protocol part of {raw, ???, _, _} is 0, not 6, since
> it's an IP level socket option (not tcp-level).
>
> btw there's also a system-wide option so you don't need to specify
> ip_freebind per socket:
>
> echo 1 > /proc/sys/net/ipv6/ip_nonlocal_bind
>
>
> RJ
>
> On 20 October 2017 at 17:17, Michael L Martin <[hidden email]> wrote:
>> Thanks for the quick response. As for what I'm  attempting to achieve, well,
>> I'm not really sure.
>>
>> I have a customer that is adamant that we use IP_FREEBIND, so I've been
>> poking around in :gen_tcp and :inet trying to see how to do that.
>>
>> Here's what happens when I try to open a listen socket:
>>
>> iex(5)> {:ok, s} = :gen_tcp.listen(8000, [{:raw, 6, 15, <<1 :: size(32)>>},
>> {:ip, {10, 138, 69, 63}}])
>> {:ok, #Port<0.1305>}
>> iex(6)> :inet.getopts(s, [{:raw, 6, 15, 4}])
>> {:ok, []}
>> iex(7)> :gen_tcp.close(s)
>> :ok
>> iex(8)> {:ok, s} = :gen_tcp.listen(8000, [{:raw, 6, 15, <<1 :: size(32)>>},
>> {:ip, {10, 138, 69, 64}}])
>> ** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}
>>
>> iex(8)>
>>
>> So it looks like it's not working for listen sockets, either. Could very
>> well be that I simply don't know what the heck I'm doing...
>>
>>
>>
>> On 2017-10-20 12:04 PM, Andreas Schultz wrote:
>>
>> Hi,
>>
>> ----- On Oct 20, 2017, at 5:10 PM, Michael L Martin <[hidden email]>
>> wrote:
>>
>> Raw socket options looks like it should be the answer, but I'm not getting
>> good results:
>>
>> iex(worker@10.138.69.63)28> {:ok, s} = :gen_tcp.connect('localhost', 80,
>> [{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 63}}])
>>
>> {:ok, #Port<0.12110>}
>>
>> iex(worker@10.138.69.63)29> :inet.getopts(s, [{:raw, 6, 15, 32}])
>>
>> {:ok, []}    <== option not set?
>>
>> iex(worker@10.138.69.63)29> {:ok, s} = :gen_tcp.connect('localhost', 80,
>> [{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 64}}])
>>
>> ** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}
>>
>>
>> IP_FREEBIND on connect doesn't make sense, it's only really useful on listen
>> sockets.
>>
>> The option lets you bind to an IP address that does not yet exist on the
>> host. That is ok for listen, but when you attempt to build an outgoing
>> connection from that IP, then it has to be configured.
>>
>> It appears that the IP_FREEBIND option is simply not set. If I use
>> IP_TRANSPARENT instead:
>>
>> iex(worker@10.138.69.63)35> {:ok, s} = :gen_tcp.connect('localhost', 80,
>> [{:raw, 6, 19, <<1>>}, {:ip, {10, 138, 69, 63}}])
>>
>> {:ok, #Port<0.12113>}
>>
>> iex(worker@10.138.69.63)34> :inet.getopts(s, [{:raw, 6, 19, 32}])
>>
>> {:ok, [{:raw, 6, 19, <<0, 0, 0, 0>>}]}
>>
>>
>> IP_TRANSPARENT needs special iptables rules to work correctly and is for a
>> very specific use case. I don't think it would be very useful for an Erlang
>> application to use that.
>>
>> In this case, the raw option 19 (IP_TRANSPARENT) is set, but to false rather
>> than true. I believe this is because the beam file needs root or
>> CAP_NET_ADMIN.
>>
>> You need root and a specific iptables setup for it to work.
>>
>> Any thoughts?
>>
>>
>> What are you attempting to achieve anyway?
>>
>> Regards
>> Andreas
>>
>>
>>
>>
>> On 2017-10-16 01:18 PM, Guilherme Andrade wrote:
>>
>> I believe you can use raw socket options[1] for that, but it won't be
>> portable.
>>
>> [1]: http://erlang.org/doc/man/inet.html#setopts-2 - {raw, Protocol,
>> OptionNum, ValueBin}
>>
>> On 16 October 2017 at 15:09, Michael L Martin <[hidden email]> wrote:
>>>
>>> Hi all,
>>>
>>> Is there a way to specify the FREEBIND option when opening a socket? I
>>> don't see any reference to it in the documentation.
>>>
>>>
>>> Thanks,
>>>
>>> _______________________________________________
>>> erlang-questions mailing list
>>> [hidden email]
>>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>>
>>
>>
>> --
>> Guilherme
>>
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> [hidden email]
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> [hidden email]
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Socket option FREEBIND

Michael L Martin
In reply to this post by Richard Jones

Posting again to all...


iex(4)> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 0, 15, <<1>>}, {:ip, {10, 138, 69, 63}}])
{:ok, #Port<0.1310>}
iex(5)> :inet.getopts(s, [{:raw, 0, 15, 4}])

{:ok, [{:raw, 0, 15, <<1, 0, 0, 0>>}]}

iex(6)> :gen_tcp.close(s) :ok

iex(7)> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 0, 15, <<1>>}, {:ip, {10, 138, 69, 64}}])

** (exit) :badarg

(kernel) gen_tcp.erl:149: :gen_tcp.connect/4

iex(7)>

I see badarg when trying to connect using a bogus IP address. But,  the option is being set now.

Using IP_TRANSPARENT instead of IP_FREEBIND:

iex(8)> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 0, 19, <<1>>}, {:ip, {10, 138, 69, 64}}])


At this point, :gen_tcp.connect/3 blocks. The ip address does not exist, so now I add it:

sudo ip addr add 10.138.69.64 dev eno1

ip addr list dev eno12: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 8c:89:a5:c6:e1:7f brd ff:ff:ff:ff:ff:ff
    inet 10.138.69.63/16 brd 10.138.255.255 scope global eno1
       valid_lft forever preferred_lft forever
    inet 10.138.69.64/32 scope global eno1
       valid_lft forever preferred_lft forever
    inet6 fe80::8e89:a5ff:fec6:e17f/64 scope link
       valid_lft forever preferred_lft forever

I would think that :gen_tcp.connect would then connect, but it's still blocked, and eventually times out.

After the timeout:

iex(8)> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 0, 19, <<1>>}, {:ip, {10, 138, 69, 64}}])
{:ok, #Port<0.1300>}
iex(9)> :inet.getopts(s, [{:raw, 0, 19, 4}])                                    {:ok, [{:raw, 0, 19, <<1, 0, 0, 0>>}]}
iex(10)>








On 2017-10-20 11:10 AM, Michael L Martin wrote:

6, 15, <<1>>}, {:ip, {10, 138, 69, 64}}])

** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}

On 2017-10-20 12:33 PM, Richard Jones wrote:
I'm able to make outbound connections bound to an arbitrary IP from my
range by specifying a socket option like: {raw, 0, 15, <<1>>}

note that that protocol part of {raw, ???, _, _} is 0, not 6, since
it's an IP level socket option (not tcp-level).

btw there's also a system-wide option so you don't need to specify
ip_freebind per socket:

echo 1 > /proc/sys/net/ipv6/ip_nonlocal_bind


RJ

On 20 October 2017 at 17:17, Michael L Martin [hidden email] wrote:
Thanks for the quick response. As for what I'm  attempting to achieve, well,
I'm not really sure.

I have a customer that is adamant that we use IP_FREEBIND, so I've been
poking around in :gen_tcp and :inet trying to see how to do that.

Here's what happens when I try to open a listen socket:

iex(5)> {:ok, s} = :gen_tcp.listen(8000, [{:raw, 6, 15, <<1 :: size(32)>>},
{:ip, {10, 138, 69, 63}}])
{:ok, #Port<0.1305>}
iex(6)> :inet.getopts(s, [{:raw, 6, 15, 4}])
{:ok, []}
iex(7)> :gen_tcp.close(s)
:ok
iex(8)> {:ok, s} = :gen_tcp.listen(8000, [{:raw, 6, 15, <<1 :: size(32)>>},
{:ip, {10, 138, 69, 64}}])
** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}

iex(8)>

So it looks like it's not working for listen sockets, either. Could very
well be that I simply don't know what the heck I'm doing...



On 2017-10-20 12:04 PM, Andreas Schultz wrote:

Hi,

----- On Oct 20, 2017, at 5:10 PM, Michael L Martin [hidden email]
wrote:

Raw socket options looks like it should be the answer, but I'm not getting
good results:

iex([hidden email])28> {:ok, s} = :gen_tcp.connect('localhost', 80,
[{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 63}}])

{:ok, #Port<0.12110>}

iex([hidden email])29> :inet.getopts(s, [{:raw, 6, 15, 32}])

{:ok, []}    <== option not set?

iex([hidden email])29> {:ok, s} = :gen_tcp.connect('localhost', 80,
[{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 64}}])

** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}


IP_FREEBIND on connect doesn't make sense, it's only really useful on listen
sockets.

The option lets you bind to an IP address that does not yet exist on the
host. That is ok for listen, but when you attempt to build an outgoing
connection from that IP, then it has to be configured.

It appears that the IP_FREEBIND option is simply not set. If I use
IP_TRANSPARENT instead:

iex([hidden email])35> {:ok, s} = :gen_tcp.connect('localhost', 80,
[{:raw, 6, 19, <<1>>}, {:ip, {10, 138, 69, 63}}])

{:ok, #Port<0.12113>}

iex([hidden email])34> :inet.getopts(s, [{:raw, 6, 19, 32}])

{:ok, [{:raw, 6, 19, <<0, 0, 0, 0>>}]}


IP_TRANSPARENT needs special iptables rules to work correctly and is for a
very specific use case. I don't think it would be very useful for an Erlang
application to use that.

In this case, the raw option 19 (IP_TRANSPARENT) is set, but to false rather
than true. I believe this is because the beam file needs root or
CAP_NET_ADMIN.

You need root and a specific iptables setup for it to work.

Any thoughts?


What are you attempting to achieve anyway?

Regards
Andreas




On 2017-10-16 01:18 PM, Guilherme Andrade wrote:

I believe you can use raw socket options[1] for that, but it won't be
portable.

[1]: http://erlang.org/doc/man/inet.html#setopts-2 - {raw, Protocol,
OptionNum, ValueBin}

On 16 October 2017 at 15:09, Michael L Martin [hidden email] wrote:
Hi all,

Is there a way to specify the FREEBIND option when opening a socket? I
don't see any reference to it in the documentation.


Thanks,

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions



--
Guilherme



_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions



_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions



_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Socket option FREEBIND

Andreas Schultz
----- On Oct 20, 2017, at 8:22 PM, Michael L Martin <[hidden email]> wrote:

Posting again to all...


iex(4)> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 0, 15, <<1>>}, {:ip, {10, 138, 69, 63}}])

Very small nitpick (does not impact the function), setsockopt boolean and integer options usually use a 32bit integer. Debugging tools like strace are much easier to read then.
So I would recommend to write the options as {:raw, 0, 15, <<1:32/native>>}

{:ok, #Port<0.1310>}
iex(5)> :inet.getopts(s, [{:raw, 0, 15, 4}])

{:ok, [{:raw, 0, 15, <<1, 0, 0, 0>>}]}

iex(6)> :gen_tcp.close(s) :ok

iex(7)> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 0, 15, <<1>>}, {:ip, {10, 138, 69, 64}}])

10.138.69.64 does not exist on you system, so attempting to use it will fail (as you just discovered).

** (exit) :badarg

(kernel) gen_tcp.erl:149: :gen_tcp.connect/4

iex(7)>

I see badarg when trying to connect using a bogus IP address. But,  the option is being set now.

Using IP_TRANSPARENT instead of IP_FREEBIND:

iex(8)> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 0, 19, <<1>>}, {:ip, {10, 138, 69, 64}}])

IP_TRANSPARENT is very different from IP_FREEBIND. You need iptables rules to make it work (and a lot more about what it is supposed to to before playing with it).

At this point, :gen_tcp.connect/3 blocks. The ip address does not exist, so now I add it:

sudo ip addr add 10.138.69.64 dev eno1

ip addr list dev eno12: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 8c:89:a5:c6:e1:7f brd ff:ff:ff:ff:ff:ff
    inet 10.138.69.63/16 brd 10.138.255.255 scope global eno1
       valid_lft forever preferred_lft forever
    inet 10.138.69.64/32 scope global eno1
       valid_lft forever preferred_lft forever
    inet6 fe80::8e89:a5ff:fec6:e17f/64 scope link
       valid_lft forever preferred_lft forever

I would think that :gen_tcp.connect would then connect, but it's still blocked, and eventually times out.

After the timeout:

iex(8)> {:ok, s} = :gen_tcp.connect('localhost', 80, [{:raw, 0, 19, <<1>>}, {:ip, {10, 138, 69, 64}}])
{:ok, #Port<0.1300>}
iex(9)> :inet.getopts(s, [{:raw, 0, 19, 4}])                                    {:ok, [{:raw, 0, 19, <<1, 0, 0, 0>>}]}
iex(10)>

As I have said before, using FREEBIND for connect makes no sense.
What you probably want it to bind a listening socket to an IP address that will later be added by systemd. For that include the raw option in the listening call.

Regards
Andreas








On 2017-10-20 11:10 AM, Michael L Martin wrote:

6, 15, <<1>>}, {:ip, {10, 138, 69, 64}}])

** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}

On 2017-10-20 12:33 PM, Richard Jones wrote:
I'm able to make outbound connections bound to an arbitrary IP from my
range by specifying a socket option like: {raw, 0, 15, <<1>>}

note that that protocol part of {raw, ???, _, _} is 0, not 6, since
it's an IP level socket option (not tcp-level).

btw there's also a system-wide option so you don't need to specify
ip_freebind per socket:

echo 1 > /proc/sys/net/ipv6/ip_nonlocal_bind


RJ

On 20 October 2017 at 17:17, Michael L Martin [hidden email] wrote:
Thanks for the quick response. As for what I'm  attempting to achieve, well,
I'm not really sure.

I have a customer that is adamant that we use IP_FREEBIND, so I've been
poking around in :gen_tcp and :inet trying to see how to do that.

Here's what happens when I try to open a listen socket:

iex(5)> {:ok, s} = :gen_tcp.listen(8000, [{:raw, 6, 15, <<1 :: size(32)>>},
{:ip, {10, 138, 69, 63}}])
{:ok, #Port<0.1305>}
iex(6)> :inet.getopts(s, [{:raw, 6, 15, 4}])
{:ok, []}
iex(7)> :gen_tcp.close(s)
:ok
iex(8)> {:ok, s} = :gen_tcp.listen(8000, [{:raw, 6, 15, <<1 :: size(32)>>},
{:ip, {10, 138, 69, 64}}])
** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}

iex(8)>

So it looks like it's not working for listen sockets, either. Could very
well be that I simply don't know what the heck I'm doing...



On 2017-10-20 12:04 PM, Andreas Schultz wrote:

Hi,

----- On Oct 20, 2017, at 5:10 PM, Michael L Martin [hidden email]
wrote:

Raw socket options looks like it should be the answer, but I'm not getting
good results:

iex([hidden email])28> {:ok, s} = :gen_tcp.connect('localhost', 80,
[{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 63}}])

{:ok, #Port<0.12110>}

iex([hidden email])29> :inet.getopts(s, [{:raw, 6, 15, 32}])

{:ok, []}    <== option not set?

iex([hidden email])29> {:ok, s} = :gen_tcp.connect('localhost', 80,
[{:raw, 6, 15, <<1>>}, {:ip, {10, 138, 69, 64}}])

** (MatchError) no match of right hand side value: {:error, :eaddrnotavail}


IP_FREEBIND on connect doesn't make sense, it's only really useful on listen
sockets.

The option lets you bind to an IP address that does not yet exist on the
host. That is ok for listen, but when you attempt to build an outgoing
connection from that IP, then it has to be configured.

It appears that the IP_FREEBIND option is simply not set. If I use
IP_TRANSPARENT instead:

iex([hidden email])35> {:ok, s} = :gen_tcp.connect('localhost', 80,
[{:raw, 6, 19, <<1>>}, {:ip, {10, 138, 69, 63}}])

{:ok, #Port<0.12113>}

iex([hidden email])34> :inet.getopts(s, [{:raw, 6, 19, 32}])

{:ok, [{:raw, 6, 19, <<0, 0, 0, 0>>}]}


IP_TRANSPARENT needs special iptables rules to work correctly and is for a
very specific use case. I don't think it would be very useful for an Erlang
application to use that.

In this case, the raw option 19 (IP_TRANSPARENT) is set, but to false rather
than true. I believe this is because the beam file needs root or
CAP_NET_ADMIN.

You need root and a specific iptables setup for it to work.

Any thoughts?


What are you attempting to achieve anyway?

Regards
Andreas




On 2017-10-16 01:18 PM, Guilherme Andrade wrote:

I believe you can use raw socket options[1] for that, but it won't be
portable.

[1]: http://erlang.org/doc/man/inet.html#setopts-2 - {raw, Protocol,
OptionNum, ValueBin}

On 16 October 2017 at 15:09, Michael L Martin [hidden email] wrote:
Hi all,

Is there a way to specify the FREEBIND option when opening a socket? I
don't see any reference to it in the documentation.


Thanks,

_______________________________________________
erlang-questions mailing list
[hidden email]http://erlang.org/mailman/listinfo/erlang-questions
--
Guilherme



_______________________________________________
erlang-questions mailing list
[hidden email]http://erlang.org/mailman/listinfo/erlang-questions



_______________________________________________
erlang-questions mailing list
[hidden email]http://erlang.org/mailman/listinfo/erlang-questions



_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions