Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

This is a followup to What's the best way to have a 169.254.169.254 address local to my laptop?. Short story: 169.254.169.254 is the "well known" address of cloud metadata services for EC2 and for OpenStack, and I want to emulate it on my laptop for devel work.

Having given up on the lo:0 approach, I decided to just set up NAT/port forwarding. My guests are configured by libvirt, using a default libvirt network which NATs through my wireless nic, which libvirt has configured like so:

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  tcp  --  192.168.77.0/24     !192.168.77.0/24      masq ports: 1024-65535
MASQUERADE  udp  --  192.168.77.0/24     !192.168.77.0/24      masq ports: 1024-65535
MASQUERADE  all  --  192.168.77.0/24     !192.168.77.0/24    

This rule:

sudo iptables -t nat -I OUTPUT -p tcp -d 169.254.169.254 --dport 80 -j DNAT --to-destination 127.0.0.1:80

does a lovely job of forwarding from Firefox running on the laptop (host OS) itself. But from within the guest, I get No route to host.

Clearly I need something else to make this work. What?


As requested, some more networking information. I removed the down interfaces from ip addr for brevity.

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether 60:67:20:44:8d:48 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.5/24 brd 192.168.1.255 scope global wlp3s0
       valid_lft forever preferred_lft forever
    inet6 fe80::6267:20ff:fe44:8d48/64 scope link
       valid_lft forever preferred_lft forever
4: virbr1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 52:54:00:84:3d:aa brd ff:ff:ff:ff:ff:ff
    inet 192.168.77.1/24 brd 192.168.77.255 scope global virbr1
       valid_lft forever preferred_lft forever

$ ip route
default via 192.168.1.1 dev wlp3s0  proto static
192.168.1.0/24 dev wlp3s0  proto kernel  scope link  src 192.168.1.5
192.168.77.0/24 dev virbr1  proto kernel  scope link  src 192.168.77.1

$ ip rule
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

$ iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination        

Chain INPUT (policy ACCEPT)
target     prot opt source               destination        

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination        

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination        
MASQUERADE  tcp  --  192.168.77.0/24     !192.168.77.0/24      masq ports: 1024-65535
MASQUERADE  udp  --  192.168.77.0/24     !192.168.77.0/24      masq ports: 1024-65535
MASQUERADE  all  --  192.168.77.0/24     !192.168.77.0/24    

$ iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination        

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination        
ACCEPT     all  --  0.0.0.0/0            192.168.77.0/24      ctstate RELATED,ESTABLISHED
ACCEPT     all  --  192.168.77.0/24      0.0.0.0/0          

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination        
share|improve this question
add comment

1 Answer 1

You need DNAT in PREROUTING and maybe also a rule in INPUT but I am not sure whether this can explain the error message. Do you have a route to this network on the host? Any fancy ip rule stuff? Please provide the output of ip addr, ip route, and ip rule.

iptables -t nat -I PREROUTING -p tcp -d 169.254.169.254 --dport 80 -j DNAT --to-destination $local_ip

Things probably get a lot easier if you can make this service listen not only on lo but also on a non-loopback interface. Say $local_ip should be rather 192.168.77.1 than 127.0.0.1.

share|improve this answer
    
It all looks pretty boring to me. Since it's Fedora 19, I was using FirewallD, which creates a lot of different (largely empty by default) zones, but I switched that off to simply things (and it doesn't help). The metadata service is listening on all addresess, so it does respond on 192.168.77.1, and in fact I can access it at that address in the guest. –  mattdm May 17 '13 at 0:24
    
And, given all that, adding the prerouting DNAT rule does not do it, I'm afraid. –  mattdm May 17 '13 at 0:27
    
"I'm afraid" means you tried it and it failed? If so do you see the packets arriving with tcpdump -i virbr1 -n? –  Hauke Laging May 17 '13 at 0:43
    
Yes, tried and failed. Ahhh! Now that's interesting. I don't get tcp packets, but I do get ARP requests: 20:48:23.758468 ARP, Request who-has 169.254.169.254 tell 192.168.77.82, length 28 (Just that, repeated.) –  mattdm May 17 '13 at 0:49
    
Soooo, I added a proxy arp entry: arp -s 169.254.169.254 -D virbr1 pub and the PREROUTING rule started working. Any idea what's up with that? Why does it care? –  mattdm May 17 '13 at 1:33
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.