Vagrant reverse port forwarding? - vagrant

I'm working on a web services architecture. I've got some software that I need to run on the native host machine, not in Vagrant. But I'd like to run some client services on the guest.
Vagrant's config.vm.forwarded_port parameter will open a port on the host and send the data to the guest. But how can I open a port on the guest and send the data to the host? (It's still port forwarding, but in the reverse direction.)

When you run vagrant ssh, it's actually using this underlying command:
ssh -p 2222 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o IdentitiesOnly=yes -i ~/.vagrant.d/insecure_private_key vagrant#127.0.0.1
SSH supports forwarding ports in the direction you want with the -R guestport:host:hostport option. So, if you wanted to connect to port 12345 on the guest and have it forwarded to localhost:80, you would use this command:
ssh -p 2222 -R 12345:localhost:80 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o IdentitiesOnly=yes -i ~/.vagrant.d/insecure_private_key vagrant#127.0.0.1
As Eero correctly comments, you can also use the command vagrant ssh -- -R 12345:localhost:80, which has the same effect in a much more concise command.

In the book Vagrant: Up and Running (Pub. date: June 12, 2013), written by the creator of Vagrant, he mentioned that it is not possible for guest machine to access services running on the host machine.
Instead of using Forwarded Ports, you could set up a private network using Host-Only Networks.
Pros of using Host-Only Networks over Forwarded Ports
Guest machines may access the services running on host machine
This feature would solve your problem.
Guest machines may access the services running on other guest machine
This feature is very useful to separate services onto multiple machines to more accurately mimic a production environment.
Secure
Outside machines have no ways to access the services running on the guest machines
Less work
No need to configure every single Forwarded Port
How to configure Host-Only Networks
config.vm.network :"hostonly", "192.168.0.0" # Vagrant Version #1
config.vm.network :private_network, ip: "192.168.0.0" # Vagrant Version #2
Having this line in your Vagrantfile will instruct vagrant to create a private network that has a static IP address: 192.168.0.0
The IP address of the host is always the same IP address but with the final octet as a 1. In the preceding example, the host machine would have the IP address 192.168.0.1.

You can access ports on the host machine through the default gateway inside the guest OS. (Which typically has an IP of 10.0.2.2.)
For example, if you have a webserver running on port 8000 on your host machine...
echo 'Hello, guest!' > hello
python -m SimpleHTTPServer 8000
You can access it from inside the Vagrant VM at 10.0.2.2:8000 (provided 10.0.2.2 is the ip of the guest's default gateway):
vagrant ssh
curl http://10.0.2.2:8000/hello # Outputs: Hello, guest!
To find the IP of the default gateway inside the guest OS, run netstat -rn (or ipconfig on a Windows guest) and look for the row with a destination IP of 0.0.0.0 (or the field labeled "Default Gateway" on Windows):
$ netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 10.0.2.2 0.0.0.0 UG 0 0 0 eth0
10.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
192.168.33.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
You can extract this IP programmatically with netstat -rn | grep "^0.0.0.0 " | tr -s ' ' | cut -d " " -f2.
Sources: How to connect with host PostgreSQL from vagrant virtualbox machine; Connect to the host machine from a VirtualBox guest OS?

Add following to your ~/.ssh/config on the host machine:
Host 127.0.0.1
RemoteForward 52698 127.0.0.1:52698
It lets you access a service on host machine port 52698 from Vagrant, as long as you logged in via vagrant ssh.
You can confirm it works by running netstat -lt on vagrant VM and taking a note on the following lines:
tcp 0 0 localhost:52698 *:* LISTEN
tcp6 0 0 ip6-localhost:52698 [::]:* LISTEN

I can access services running on my host machine via its local IP address (not its loopback address). I tested by creating an http server on port 80 (and then on port 987) and curling 197.45.0.10:80 and 197.45.0.10:987 (actual ip address changed to protect the innocent). It worked both times, and I don't have any special vagrant configuration (no public_network, no forwarded_port) and while I do have some ports forwarded via PuTTY, I don't have ports 80 and 987 forwarded. So maybe try using the host machine's local or public IP address.
And if you want to access (ssh into) one guest vagrant instance from another, you can enable public_network as well as forwarding from port 22 in the Vagrantfile like this:
config.vm.network "public_network"
config.vm.network "forwarded_port", guest: 22, host: 2200
Then as long as that port is open (ie do some more port forwarding in your router config) you can access that machine from anywhere, even the outside world.

Related

Vagrant port fowarding on macOS?

I'm running postgresql on a Vagrant centos 7.2 box on macOS. I have confirmed postgres is up and running on the Vagrant box on port 5432 by connecting to it using psql on the box itself. I am attempting to forward port 5432 on the Vagrant box to port 10001 on my host machine as follows:
config.vm.define "acc_db" do | acc_db |
acc_db.vm.box = "bento/centos-7.2"
acc_db.vm.hostname = "acc.db"
acc_db.vm.network :forwarded_port, guest: 5432, host: 10001
acc_db.vm.provision "shell",
inline: "yum upgrade -y -q --nogpgcheck"
acc_db.vm.provision "shell",
path: "install_postgres.sh"
I have altered my pg_hba.conf to bind to all ip addresses and allow password authentication, as below:
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all peer
# IPv4 local connections:
host all all 0.0.0.0/0 md5
# IPv6 local connections:
host all all ::1/128 ident
I have turned off the firewall but I am still unable to connect to postgres on port 10001 on the host machine:
psql: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/tmp/.s.PGSQL.10001"?
How do I fix this so that port forwarding works?
I have seen https://gielberkers.com/fixing-vagrant-port-forwarding-osx-yosemite/ but haven't tried it as it involves touching files I'm unfamiliar with. Is it the correct approach? It looks like you have to explicitly allow every port you want to forward via Vagrant.
...connections on Unix domain socket "/tmp/.s.PGSQL.10001" means that you are not attempting a TCP/IP connection, so port forwarding cannot happen.
By default, psql use Unix domain sockets on unix-like OSes.
Use the -h option of psql to specify a host, presumably 127.0.0.1 if using IPv4.
Additionally, the PostgreSQL server must listen to the network interface to which the connection will be routed. By default, it listens only to localhost for security reasons.
Setting listen_addresses='*' in postgresql.conf makes it listen on all existing interfaces.

How can I access a vagrant guest from another virtualbox guest?

The scenario is that my dev environment is on a Vagrant box on my laptop (host) and I would like to do browser testing in a vitualbox vm, so I need to see one vm from another.
The vagrant box's port is :8080 which is forwarded to the host on the same port :8080. So I can see the server from the host at localhost:8080
Which address should I be using for the browser testing vm?
The testing vm's default gateway?
The vagrant vm's ip?
The host's virtual network ip?
And should I be using a NAT or host only adapter on the browser testing vm?
That makes for a lot of combinations, all of which I believe I have tried. What else do I need to understand here?
In your use case, you should be using Bridged networking (Public Network in Vagrant). If the VMs reside on the same host, you can even use internal (Private Network in Vagrant).
If using Public Network, the VM's 2nd NIC will be able to obtain an IP address from the DHCP server in your network (e.g. your home router).
Simply add the following code block in your Vagrantfile and do a vagrant reload
Vagrant.configure("2") do |config|
config.vm.network "public_network"
end
You should be able to get the IP address by using vagrant ssh and ifconfig / ip addr show.
In case you don't want to go with public_network just like me then you should do the steps below using private_network:
Open Vagrantfile from your project root
Search for config.vm.network
Add this line config.vm.network "private_network", ip: "192.168.33.10". Remember this is not the IP of your base machine it's a virtual-box IP address and your machine IP should be different. You can say it's a fake IP address so change it to anything else like 192.168.30.20.
Reload your vagrant using vagrant reload.
Now go to your other virtual guest in my case it's the Windows Guest 2. My base is Linux Mint Vagrant box is on Ubuntu Guest 1. Open C:\Windows\System32\drivers\etc\hosts file as admin and do the above IP's entry in there like 192.168.33.10 local.youralias.com. And save the file, after that you can now browse the site now at http://local.youralias.com/.
In case your guest 2 is also Linux just edit this file sudo vi /etc/hosts, and add this line at top of it 192.168.33.10 local.youralias.com. Now save and exit and browse the URL :)
Enjoy! Happy coding.
Adding to accepted answer, you can actually set IP and specify which network interface to use.
My setup on linux box via wifi and static IP:
You can find your wifi interface name by running ifconfig command.
Vagrant.configure("2") do |config|
config.vm.network "public_network", :bridge => 'wlp8s0', ip: "192.168.1.199"
end
This may have many source cause. In my case, I use vagrant fedora boxe.
I tried:
First using the private_network that I attached to a host only adapter and launched httpd service to test the connection between guest and host
config.vm.network "private_network", type: "dhcp", name: "vboxnet2"
config.vm.network "forwarded_port", guest:80, host:7070
but I was not able to ping my guest machine from the host and could no telnet the httpd service opened
Second using public_network and launched httpd service to test connectivity
config.vm.network "public_network", bridge: "en0: Wi-Fi (AirPort)", use_dhcp_assigned_default_route: true
I could ping my guest from my host but I could not telnet the httpd service.
For this two use case, the issue was that the port 80 on the fedora guest host was blocked by the firewall. Here is what fixed the issue and get all working for both privat_network and public_ntwork:
firewall-cmd --permanent --add-port 80/tcp #open the port permanently
firewall-cmd --zone=public --permanent --add-service=http
firewall-cmd --list-port # list to check if the port was opened
systemctl stop firewalld # stop and open the firewall service
systemctl start firewalld
Old question, new answer: [disclaimer: i am not a vagrant expert]
both solutions might work but the solution in the "vagrant way of thinking" is that some component in your guest (rinetd?) should forward any requests to unknown ports to the host. From the host the request could then be mapped (via vagrant port forwarding) to a services that is running in the other guest.
So, to resume:
1.in guest-1 we do localhost:1234. Guest-1 will detect that this port is not available and forward to host
2. the host will check the vagrant port forwarding and forward to guest-2
3. in guest-2 we have some nice service listening to post 1234
4. done.

How to tunnel host traffic through guest in Virtualbox using Vagrant

I have a Ubuntu host and an Ubuntu guest. I want to achieve that my host traffic is tunnelled through my guest. Thus enabling me to do analysis on the host traffic from the guest. I am assigning two interfaces to the guest (in addition to the built in NAT interface which is provided by Vagrant). I am creating a bridge interface on the host called br0. One of the guest interfaces is connected via bridging to eth0 (the host interface which is connected to the Internet) and the other guest interface is connected via bridging to the host br0 interface. On the host I am deleting my default gateway and adding a new one with:
route del default
route add default dev br0
After that I can vagrant ssh into my guest and set up a bridge interface there as well with.
brctl addbr br0
brctl addif br0 eth1
brctl addif br0 eth2
After this setup the host traffic should be routed through the guest. If I run
tcpdump -vni br0
inside the guest I can see packets but I can't connect to the Internet. There is something missing. Any ideas?
I had to enable IPv4 forwarding in the guest.
Edit /etc/sysctl.conf to enable forwarding permanently:
net.ipv4.ip_forward = 1
Run this to activate the setting without a reboot:
sysctl -p /etc/sysctl.conf

Boot2Docker: Connect to container over LAN

I'm using Boot2Docker 1.3.0 on my Mac and I'm pretty happy so far using it. But now I'd like to connect to a http container (exposes port 8080) not from my local machine but from another machine in my local network? If I'm doing it locally I just use http://192.168.59.103:8080 so I'm using the ip address of the docker host. This can't work for other machines in my local network but using the ip address of my mac does not work either. I'm pretty sure there are some solutions for this problem but I can't find any. It can't be that hard right? What I want is to make a request to http://[IP-Address-of-mac]:8080 from another host in my local network. I think I have to set up some routing rules on my local machine right? May anybody tell me what to do? Thanks in advance.
Best regards
Sascha
You need to port forward from the OSX box to the virtual machine
VBoxManage modifyvm "boot2docker-vm" --natpf1 "tcp-port8080,tcp,,8080,,8080";
should do the trick
or, you could use ssh based port forwarding:
boot2docker ssh -L 8000:localhost:8000
see https://github.com/boot2docker/boot2docker/blob/master/doc/WORKAROUNDS.md
On your Mac, determine the IP address that it uses on your local LAN:
$ ifconfig | grep 192
inet 192.168.1.21 netmask 0xffffff00 broadcast 192.168.1.255
inet 192.168.59.3 netmask 0xffffff00 broadcast 192.168.59.255
Then port forward:
$ boot2docker ssh -vnNTL 192.168.1.21:8080:localhost:8080
Now, requests that come into your Mac on port 8080 will get forwarded to the boot2docker Linux VM on port 8080. The docker server will then forward from the exposed port (VM port 8080) to the port your container is using for httpd (probably 80).
Note that "localhost" above is from the point of view of the Linux VM, not the Mac, because that is the host you are ssh'ing into.

Two separate Vagrant machines, windows host, PuTTY - how?

I'd like to create two vagrant machines via two vagrant files, and be able to ssh into them via PuTTY.
I thought it might be as simple as port forwarding one of them via, say, port 2223 instead of 2222, and using two PuTTY connections.
Despite my vagrant ssh-config looking like this:
HostName 127.0.0.1
User vagrant
Port 2223
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile "XXXXXXXXXXXXXXXXXXXXXXXXXXX"
IdentitiesOnly yes
LogLevel FATAL
... I seem able to ssh into it via PuTTY on port 2222, which I'm hoping to reserve for access to the other instance which I've not yet set up. I'm new to vagrant and may be making a noob mistake. Help appreciated.
As per Vagrant Base Box specification, the default networking mode is NAT and port forwarding for SSH is enabled (guest 22 => host 2222).
What you've done, changing the sshd_config file within the guest won't work because that only changes the SSH port within the guest to 2223, NOT the host.
For the 2nd vagrant box, you need to do the following:
Get the name or UUID VBoxManage list vms
Use VBoxManage showvminfo VM_Name to get the list of port forwarding rules
Delete its default guestssh NAT port forwarding rule
Add a new port forwarding rule to do guest 22 => host 2223
For example:
By default the rule is named ssh
NIC 1 Rule(1): name = ssh, protocol = tcp, host ip = 127.0.0.1, host port = 2222, guest ip = , guest port = 22
Delete it
VBoxManage modifyvm "VM_Name" --natpf1 delete "ssh"
Add a new rule
VBoxManage modifyvm base_box --natpf1 "guestssh, tcp,,2223,,22"
NOT DONE yet!!!
Do NOT use vagrant up to start this VM, because it'll add the ssh rule back.
You can use VirtualBox GUI or VBoxManage controlvm to start it. And connect to it using ssh -p 2223 vagrant#localhost, password is vagrant. You can also use the insecure key pair to do public key authentication, doesn't make much sense though.
NOTE: changing, adding and deleting port forwarding rules can be done using the VirtualBox GUI anyway, if it is easier for you.
You can set any port you like by putting this in your vagrantfile:
config.vm.network "forwarded_port", guest: 22, host: 2223
replacing 2223 with your port of choice - different for each VM, obviously.
Note that this is in addition to the standard 2222 port forwarding, which will still be mapped for every VM. One of them "wins" and answers on 2222 as well as whatever custom port you set up.
The procedure in the accepted answer may well work, but it seems a little convoluted.

Resources