listen tcp 127.0.4.1:2040: bind: can't assign requested address - macos

I am using this golang code:
l, err := net.Listen("tcp", "127.0.4.1:2040")
if err != nil {
log.Fatal("d0b9184a-5248-413e-a5a8-30fea66997f5:", err)
}
log.Fatal(s.Serve(l))
I am getting this error:
listen tcp 127.0.4.1:2040: bind: can't assign requested address
anyone know why that won't work?

You have to add an additional IPv4 address to the loopback interface:
sudo ifconfig lo0 alias 127.0.4.1
Before running the command you can verify the routes using:
netstat -nr
By default (On MacOS Catalina 10.15.4), these routes are present:
127 127.0.0.1 UCS lo0
127.0.0.1 127.0.0.1 UH lo0
After you have added your desired address to the loopback interface (i.e, lo0), netstat -nr would show:
127 127.0.0.1 UCS lo0
127.0.0.1 127.0.0.1 UH lo0
127.0.4.1 127.0.4.1 UH lo0
Now try using your program, it should work.
Also, this is temporary. It won't persist on reboot. For that give this a read!

Related

Adding a multicast route to an interface in OSX

I have a VM running in Fusion that I want to hit by routing a specific endpoint address through the virtual ethernet interface (multicast DNS, in particular). First I was sending packets and inspecting with Wireshark noticing that nothing was getting through. Then I thought to check the routing table
$ netstat -rn | grep vmnet8
Destination Gateway Flags Refs Use Netif Expire
172.16.12/24 link#29 UC 2 0 vmnet8 !
172.16.12.255 ff:ff:ff:ff:ff:ff UHLWbI 0 35 vmnet8 !
But unlike other interfaces,
Destination Gateway Flags Refs Use Netif Expire
224.0.0.251 a1:10:5e:50:0:fb UHmLWI 0 732 en0
224.0.0.251 a1:10:5e:50:0:fb UHmLWI 0 0 en8
There was no multicast route. So I added it:
$ sudo route add -host 224.0.0.251 -interface vmnet8
add host 224.0.0.251: gateway vmnet8
And so it was true
$ netstat -rn | grep vmnet8
Destination Gateway Flags Refs Use Netif Expire
172.16.12/24 link#29 UC 2 0 vmnet8 !
172.16.12.255 ff:ff:ff:ff:ff:ff UHLWbI 0 35 vmnet8 !
224.0.0.251 a1:10:5e:50:0:fb UHmLS 0 13 vmnet8
I was also sure to check the interface flags to ensure it had been configured to support multicast
$ ifconfig vmnet8
vmnet8: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
ether 00:70:61:c0:11:08
inet 172.16.12.1 netmask 0xffffff00 broadcast 172.16.12.255
Still, no multicast packets I send are getting through. I noted that the other interface's multicast route have different flags than the default ones given to my added route. Namely UHmLWI vs UHmLS. The differences I can see are insignificant. From man netstat:
I RTF_IFSCOPE Route is associated with an interface scope
S RTF_STATIC Manually added
W RTF_WASCLONED Route was generated as a result of cloning
Then again, I'm not claiming to be a routing expert. Perhaps a multicast route entry must be made somehow differently?
You'll note that the Use column is non-zero, despite no packets showing in a sniffer.

Go net.DialUDP auto-selecting loopback interface

I have a need to send some UDP packets from eth0 on a host to itself, also on eth0.
I have some working Go code, but it appears to be using the loopback interface instead of eth0 as expected.
package main
import (
"net"
)
func main() {
ip := net.ParseIP("192.168.1.158")
src := net.UDPAddr{IP: ip, Port: 8888,}
dest := net.UDPAddr{IP: ip, Port: 88}
conn, _ := net.DialUDP("udp", &src, &dest)
conn.Write([]byte("hi"))
}
192.168.1.158 is the primary and only IP address for the interface on my machine.
Running the following command shows me the traffic:
sudo tcpdump udp -v -i lo
However, I would expect the traffic be to/from the system interface with the IP address I've defined.
Am I missing a step here?
I have also tried this slightly different approach, but with the same results:
src, _ := net.ResolveUDPAddr("udp", "192.168.1.158:8888")
dest, _ := net.ResolveUDPAddr("udp", "192.168.1.158:88")
However, I would expect the traffic be to/from the system interface with the IP address I've defined.
This is simply the wrong expectation and unrelated to Go.
Just try ping 192.168.1.158 and check with tcpdump -i lo -n icmp vs. tcpdump -i eth0 -n icmp where the data actually gets transferred. You will see that the packets are transferred on the lo interface. Similar a ip route get 192.168.1.158 will show you that the route to your local address goes through the lo interface.

`hostname -i` address differs from `ifconfig` address

Resolving my local hostname (the one returned by hostname) does not yield the right ip address. Why could that be and how do I fix it?
$ hostname -i
10.21.16.206
$ ping 10.21.16.206
PING 10.21.16.206 (10.21.16.206) 56(84) bytes of data.
From 10.21.16.159 icmp_seq=1 Destination Host Unreachable
$ ifconfig
(...)
inet 10.21.16.159 netmask 255.255.252.0 broadcast 10.21.19.255
(...)
10.21.16.206 != 10.21.16.159
$ host 10.21.16.159
Host 159.16.21.10.in-addr.arpa. not found: 3(NXDOMAIN)
$ host 10.21.16.206
206.16.21.10.in-addr.arpa domain name pointer lxka-czc1166cxw.united.domain.
$ resolveip 10.21.16.159
Host name of 10.21.16.159 is lxka-czc1166cxw
$ resolveip 10.21.16.206
Host name of 10.21.16.206 is lxka-czc1166cxw.united.domain
Help is very much appreciated!
Edit:
$ host $(hostname)
lxka-czc1166cxw.united.domain has address 10.21.16.206
hostname -i relies on DNS resolution to return the IP address of the given hostname. Either your /etc/hosts or dns resolver return that hostname to the incorrect IP address.
from man page of hostname:
option -i, --ip-address
Display the network address(es) of the host name. Note that this works only if the host name can be resolved. Avoid using this option;
use hostname --all-ip-addresses or
To use the hostname -I option instead of it.

execute shell script in ruby

I want to execute the following shell script
system('echo "
rdr pass on lo0 inet proto tcp from any to 192.168.99.1 port 80 -> 192.168.99.1 port 8080
rdr pass on lo0 inet proto tcp from any to 192.168.99.1 port 443 -> 192.168.99.1 port 4443
" | sudo pfctl -ef - > /dev/null 2>&1; echo "==> Fowarding Ports: 80 -> 8080, 443 -> 4443 & Enabling pf"'
)
This works fine, i now want to pass the IP address loaded from a YAML file, i tried the following
config.yaml
configs:
use: 'home'
office:
public_ip: '192.168.99.2'
home:
public_ip: '192.168.99.1'
Vagrantfile
require 'yaml'
current_dir = File.dirname(File.expand_path(__FILE__))
configs = YAML.load_file("#{current_dir}/config.yaml")
vagrant_config = configs['configs'][configs['configs']['use']]
system('echo "
rdr pass on lo0 inet proto tcp from any to '+vagrant_config['public_ip']+' port 80 -> '+vagrant_config['public_ip']+' port 8080
rdr pass on lo0 inet proto tcp from any to '+vagrant_config['public_ip']+' port 443 -> '+vagrant_config['public_ip']+' port 4443
" | sudo pfctl -ef - > /dev/null 2>&1; echo "==> Fowarding Ports: 80 -> 8080, 443 -> 4443 & Enabling pf"'
)
The second method does not work, nor it shows any error, can someone point me to the right direction, what i want is to read public_ip dynamically from config file or variable
Thanks
UPDATE 1
I get the following output
pfctl: Use of -f option, could result in flushing of rules
present in the main ruleset added by the system at startup.
See /etc/pf.conf for further details.
No ALTQ support in kernel
ALTQ related functions disabled
pfctl: pf already enabled
What can be possibly wrong?
For troubleshooting purposes, it would be wise to output the command you're going to run prior to sending it out to system.
cmd = 'echo "
rdr pass on lo0 inet proto tcp from any to '+vagrant_config['public_ip']+' port 80 -> '+vagrant_config['public_ip']+' port 8080
rdr pass on lo0 inet proto tcp from any to '+vagrant_config['public_ip']+' port 443 -> '+vagrant_config['public_ip']+' port 4443
" | sudo pfctl -ef - > /dev/null 2>&1; echo "==> Fowarding Ports: 80 -> 8080, 443 -> 4443 & Enabling pf"'
puts "Command to run:\n\n#{cmd}"
system( cmd )
Then, it would be wise to make the output from the system command visible. To make sure you get this feedback, I suggest you replace
sudo pfctl -ef - > /dev/null 2>&1
with (adding '-v' for more verbose output - pfctl man page)
sudo pfctl -efv -
and then look for the output and/or error messages.
Then, once the bugs are sorted out, you can put it back into stealthy, quiet mode :D
Also, since you are running with sudo you'll need to make sure the shell you're running within has sudo privileges and also make sure you're not being prompted for a password unknowingly.

How to enable routing in OS X El Capitan

I've got a Linux VMware virtual machine (guest) configured with a NAT adapter on a 192.168.56.0 subnet. Its IP address is 192.168.56.128 and my Mac (host) got 192.168.56.1. Guest's default gateway is automatically set to 192.168.56.2 and is able to ping google. Host's Wi-Fi IP is 192.168.0.2,
I've configured my Wi-Fi router with following routing table to forward packets of 192.168.56.0 to 192.168.0.2 (my Mac)
pi#raspberrypi ~ $ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 172.16.4.1 0.0.0.0 UG 0 0 0 eth0
172.16.4.0 * 255.255.252.0 U 0 0 0 eth0
192.168.0.0 * 255.255.255.0 U 0 0 0 wlan0
192.168.56.0 192.168.0.2 255.255.255.255 UGH 0 0 0 wlan0
192.168.57.0 192.168.0.2 255.255.255.255 UGH 0 0 0 wlan0
But I'm unable to ping guest from any other device on the Wi-Fi network (192.168.0.0). So it's obvious that my Mac running OS X El Capitan is not forwarding the packets from 192.168.0.0 to 192.168.56.0
Not sure about your specific case. In my case I just had two ethernets on the same MacMini and one host being one of these ethernets. The only thing I had to do is sudo sysctl -w net.inet.ip.forwarding=1
https://roelant.net/2015/share-your-vpn-mac-el-capitan.html however noted another variable as well (sudo sysctl -w net.inet.ip.fw.enable=1) and went into a NAT scenario (which I did not need)

Resources