# bind a shell program to a specific ip



## antolap (Sep 12, 2017)

If I have a program (that I run from shell) which hasn't an option itself to bind to a particular ip (the machine has a lot of ip addresses) is there a way to tell that it must use a particular ip?

I mean without having to recompile the kernel with setfib option

Thanks

p.s.: why don't you make setfib a default options in FreeBSD ?


----------



## tobik@ (Sep 12, 2017)

antolap said:


> If I have a program (that I run from shell) which hasn't an option itself to bind to a particular ip (the machine has a lot of ip addresses) is there a way to tell that it must use a particular ip?


Run it in a jail and assign the IP to it.

`jail -c path=/ host.hostname=blablabla name=foobar ip4.addr=$IP command=/path/to/your/command`



antolap said:


> I mean without having to recompile the kernel with setfib option
> 
> Thanks
> 
> p.s.: why don't you make setfib a default options in FreeBSD ?


It's enabled by default in the GENERIC kernel already (Is there even an option to disable it?). setfib is for setting the routing table a process uses, I don't see how this is relevant to binding a process to a specific IP.


----------



## sko (Sep 12, 2017)

I suspect the script is starting some kind of service/socket/listener, e.g. via nc. If you don't want or cannot modify the script, you could also use "setfib" to use a trimmed-down routing table with a default route via the desired interface.
This approach only affects the outgoing connections by the service - it is still possible to send data to it via other IPs, but responses will be send via the interface relating to the default route. This essentially breaks most/any stateful protocols!

Multiple FIBs is already enabled in the GENERIC kernel, as tobik@ already pointed out. However, to use multiple FIBs one has to increase the value of `net.fibs` via /boot/loader.conf.

The better solution would be to modify the script or run it within a jail as tobik@ already suggested.


----------



## antolap (Sep 13, 2017)

> Run it in a jail and assign the IP to it.
> 
> jail -c path=/ host.hostname=blablabla name=foobar ip4.addr=$IP command=/path/to/your/command



It seems to work
I don't understand how to close the jails

If I run the command, it works, but if I do `jls`  I see that the jail number 1 is still open

so If I run 100 commands, I'll have 100 running jails

questions:
1. Would be it possibile to kill the jail, when the command is closed?
2. if I have to close manually the jails, after command is ended, is there a way to close all jails? something like: `jail -r ANY`





> Multiple FIBs is already enabled in the GENERIC kernel, as tobik@ already pointed out. However, to use multiple FIBs one has to increase the value of



Ok FIBs work also wihout having to recompile kernel
I'd like to understand one thing: I have 8 network cards
can I use ethernet card 1 in setfib 1, ethernet card 2 in setfib 2, ethernet card 3 in setfib 3, so that if I do`setfib3 iconfig`, I see ONLY ethernet card 3 ?


----------



## tobik@ (Sep 13, 2017)

antolap said:


> 1. Would be it possibile to kill the jail, when the command is closed?


That should happen automatically when the commands exits (unless you specify persist on the jail command line). Maybe your command leaves some processes behind? Check with `ps ax -J ${jail name or id}`



antolap said:


> if I have to close manually the jails, after command is ended, is there a way to close all jails?


That should be possible with `jail -R '*'`, but you really should investigate why the jails are not exiting like they should...


----------



## antolap (Sep 13, 2017)

this is a test with a generic program (in this case ping)


```
root@freebsd2g-11:~ # jls
   JID  IP Address      Hostname                      Path
root@freebsd2g-11:~ # jail -c allow.raw_sockets ip4.addr=192.168.150.8 command=ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: icmp_seq=0 ttl=55 time=29.823 ms
64 bytes from 8.8.8.8: icmp_seq=1 ttl=55 time=29.361 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=55 time=29.863 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=55 time=29.359 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=55 time=29.358 ms
^C
--- 8.8.8.8 ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 29.358/29.553/29.863/0.237 ms

root@freebsd2g-11:~ # jls
   JID  IP Address      Hostname                      Path
    38  192.168.150.8                                 /
root@freebsd2g-11:~ #  ps ax -J 38
PID TT  STAT TIME COMMAND
root@freebsd2g-11:~ #
```

In this case I have used control c to end the ping


If instead of ping 8.8.8.8 the command is ping -c 4 8.8.8.8, the jail is closed when ping ends

I suppose that the system check the exit state of ping or something like this
no other processes are running


----------



## sko (Sep 14, 2017)

antolap said:


> I'd like to understand one thing: I have 8 network cards
> can I use ethernet card 1 in setfib 1, ethernet card 2 in setfib 2, ethernet card 3 in setfib 3, so that if I do setfib3 iconfig, I see ONLY ethernet card 3 ?



FIBs are just routing tables - they have nothing to do with what NICs are shown when running ifconfig(8).
Given you assign addresses of different subnets to each of the NICs, you can set default routes on different tables matching these subnets.

If you assign a jail an address on a specific interface, the jail will only use this interface. Jails can also use a specific FIB (exec.fib), so you can match the jails routes to the interface/subnet it is using.

From your question on how to "close" a jail and how you are using it only to run single commands, I suspect you didn't fully understand what a jail is. Have a look at the FreeBSD Handbook on this topic:
https://www.freebsd.org/doc/handbook/jails.html


----------



## antolap (Sep 14, 2017)

I have read the manual, but I need to run single commands, not run servers inside jails 24hours/day

other question:
If I have a static ip address on interface I can do:

```
jail -c allow.raw_sockets ip4.addr=192.168.3.3 command=....
```
and it's OK


If I have a dynamic ip on interface, for example a dynamic ip on interface TUN0,
how can I let the jail to use TUN0 ip address and not all other ip address on different interfaces?
If I do:

```
jail -c allow.raw_sockets interface=tun0 command=....
```
it doesn't work


----------



## antolap (Dec 3, 2017)

I have found this
http://daniel-lange.com/archives/53-Binding-applications-to-a-specific-IP.html
which works in Linux

is there a way to compile this in FreeBSD?

I get some errors

```
bind.c: In function '_init':
bind.c:82:21: warning: implicit declaration of function 'inet_addr' [-Wimplicit-function-declaration]
   bind_addr_saddr = inet_addr (bind_addr_env);
                     ^~~~~~~~~
/usr/local/bin/ld: cannot find -ldl
collect2: error: ld returned 1 exit status
```

or is it tailored for Linux only?

isn't there a similar alternative for FreeBSD without using jails?


----------

