{"id":2444,"date":"2018-04-01T15:16:01","date_gmt":"2018-04-01T20:16:01","guid":{"rendered":"http:\/\/osric.com\/chris\/accidental-developer\/?p=2444"},"modified":"2018-04-02T20:23:24","modified_gmt":"2018-04-03T01:23:24","slug":"python-flask-and-virtualbox-networking","status":"publish","type":"post","link":"https:\/\/osric.com\/chris\/accidental-developer\/2018\/04\/python-flask-and-virtualbox-networking\/","title":{"rendered":"Python Flask and VirtualBox networking"},"content":{"rendered":"<p>I had been using the Python socket module to create a very basic client-server for testing purposes, but soon I wanted to have something slightly more standard, like an HTTP server. I decided to try the Python Flask framework.<\/p>\n<p>First I set up a Flask server on a CentOS 7 Linux VM running on VirtualBox:<\/p>\n<pre><code># yum install python-pip\r\n# pip install Flask\r\n# mkdir flask-server &amp;&amp; cd flask-server<\/code><\/pre>\n<p>I created the <code>hello.py<\/code> file as described on the <a href=\"http:\/\/flask.pocoo.org\/\">Flask homepage<\/a>:<\/p>\n<pre><code>from flask import Flask\r\napp = Flask(__name__)\r\n\r\n@app.route(\"\/\")\r\ndef hello():\r\n    return \"Hello World!\"<\/code><\/pre>\n<p>Likewise, I started running Flask:<\/p>\n<pre><code># FLASK_APP=hello.py flask run\r\n * Serving Flask app \"hello\"\r\n * Running on http:\/\/127.0.0.1:5000\/ (Press CTRL+C to quit)<\/code><\/pre>\n<p>Then I set up port forwarding in VirtualBox on my desktop host so that I could communicate with the virtual machine, using the following settings:<\/p>\n<p><code>Name: flask<br \/>\nProtocol: TCP<br \/>\nHost IP: 127.0.0.1<br \/>\nHost Port: 9500<br \/>\nGuest IP: 10.0.2.16<br \/>\nGuest Port: 5000<\/code><\/p>\n<figure id=\"attachment_2460\" aria-describedby=\"caption-attachment-2460\" style=\"width: 678px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/osric.com\/chris\/accidental-developer\/2018\/04\/python-flask-and-virtualbox-networking\/virtualbox-port-forwarding-rules\/\" rel=\"attachment wp-att-2460\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/osric.com\/chris\/accidental-developer\/wp-content\/uploads\/2018\/04\/virtualbox-port-forwarding-rules.png\" alt=\"VirtualBox port forwarding rules\" width=\"678\" height=\"449\" class=\"size-full wp-image-2460\" srcset=\"https:\/\/osric.com\/chris\/accidental-developer\/wp-content\/uploads\/2018\/04\/virtualbox-port-forwarding-rules.png 678w, https:\/\/osric.com\/chris\/accidental-developer\/wp-content\/uploads\/2018\/04\/virtualbox-port-forwarding-rules-300x199.png 300w\" sizes=\"auto, (max-width: 678px) 100vw, 678px\" \/><\/a><figcaption id=\"caption-attachment-2460\" class=\"wp-caption-text\">VirtualBox port forwarding rules<\/figcaption><\/figure>\n<p>I tested it in a browser (Firefox) on my desktop at <code>http:\/\/127.0.0.1:9500\/<\/code><\/p>\n<p>No connection. Firefox endlessly tries to load the file.<\/p>\n<p>I tried from the local machine itself:<\/p>\n<pre><code># curl http:\/\/localhost:5000\/\r\nHello World!<\/code><\/pre>\n<p>I tried running <code>tcpdump<\/code> to see what the network traffic to that port looked like:<\/p>\n<pre><code># tcpdump -n -i enp0s3 port 5000\r\n...\r\n14:54:11.938625 IP 10.0.2.2.63923 &gt; 10.0.2.16.commplex-main: Flags [S], seq 3067208705, win 65535, options [mss 1460], length 0\r\n...<\/code><\/pre>\n<p>Over and over I saw the same SYN packet from the client host, but the server never replied with a SYN-ACK.<\/p>\n<p>I also noted that the local port was labeled <code>commplex-main<\/code>. This label is from <code>\/etc\/services<\/code>:<\/p>\n<pre><code># grep commplex \/etc\/services\r\ncommplex-main   5000\/tcp                #\r\ncommplex-main   5000\/udp                #\r\ncommplex-link   5001\/tcp                #\r\ncommplex-link   5001\/udp                #<\/code><\/pre>\n<p>I don&#8217;t know what <code>commplex-main<\/code> is, but since I&#8217;m not running anything else on port 5000 other than Flask, it shouldn&#8217;t matter.<\/p>\n<p>It turned out there were 2 separate problems:<\/p>\n<ol>\n<li>Flask was listening only on localhost<\/li>\n<li>firewalld was blocking the requests from external hosts<\/li>\n<\/ol>\n<p>To fix the first, run Flask with the host flag:<\/p>\n<pre><code># FLASK_APP=hello.py flask run --host=0.0.0.0\r\n * Serving Flask app \"hello\"\r\n * Running on http:\/\/0.0.0.0:5000\/ (Press CTRL+C to quit)<\/code><\/pre>\n<p>(This is mentioned in the Flask Quickstart guide, under <a href=\"http:\/\/flask.pocoo.org\/docs\/0.12\/quickstart\/#public-server\">Externally Visible Server<\/a>.)<\/p>\n<p>You can also specify an alternative port, e.g.:<\/p>\n<pre><code># FLASK_APP=hello.py flask run --host=0.0.0.0 --port=56789\r\n * Serving Flask app \"hello\"\r\n * Running on http:\/\/0.0.0.0:56789\/ (Press CTRL+C to quit)<\/code><\/pre>\n<p>To fix the latter temporarily, I disabled <code>firewalld<\/code>:<\/p>\n<pre><code>systemctl stop firewalld\r\nsystemctl disable firewalld<\/code><\/pre>\n<p>Obviously, if you are dealing with a machine connected directly to the Internet, this would be a terrible solution. You&#8217;d want to add rules allowing only the hosts and ports from which you expect to receive connections. But for testing communications between my desktop and a virtual host running on it, this seemed like a quick solution.<\/p>\n<p>After those 2 changes, I was able to load the sample &#8220;hello&#8221; Flask app in a browser:<\/p>\n<figure id=\"attachment_2461\" aria-describedby=\"caption-attachment-2461\" style=\"width: 469px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/osric.com\/chris\/accidental-developer\/2018\/04\/python-flask-and-virtualbox-networking\/hello-world-port-9500\/\" rel=\"attachment wp-att-2461\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/osric.com\/chris\/accidental-developer\/wp-content\/uploads\/2018\/04\/hello-world-port-9500.png\" alt=\"The text &quot;Hello World!&quot; loaded in Firefox\" width=\"469\" height=\"247\" class=\"size-full wp-image-2461\" srcset=\"https:\/\/osric.com\/chris\/accidental-developer\/wp-content\/uploads\/2018\/04\/hello-world-port-9500.png 469w, https:\/\/osric.com\/chris\/accidental-developer\/wp-content\/uploads\/2018\/04\/hello-world-port-9500-300x158.png 300w\" sizes=\"auto, (max-width: 469px) 100vw, 469px\" \/><\/a><figcaption id=\"caption-attachment-2461\" class=\"wp-caption-text\">The text &#8220;Hello World!&#8221; loaded in Firefox<\/figcaption><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>The 7-line &#8220;Flask is fun and easy to set up&#8221; example on the Flask home page didn&#8217;t work for me until I made a few tweaks to my VirtualBox network port forwarding, updated the host flag passed to Flask, and updated firewall settings on the Flask server host.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[86],"tags":[453,492,358,493,421],"class_list":["post-2444","post","type-post","status-publish","format-standard","hentry","category-python","tag-firewalld","tag-flask","tag-python","tag-tcpdump","tag-virtualbox"],"_links":{"self":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/2444","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/comments?post=2444"}],"version-history":[{"count":8,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/2444\/revisions"}],"predecessor-version":[{"id":2474,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/2444\/revisions\/2474"}],"wp:attachment":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/media?parent=2444"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/categories?post=2444"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/tags?post=2444"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}