{"action":"created","comment":{"url":"https://api.github.com/repos/niksu/pax/pulls/comments/71776593","id":71776593,"diff_hunk":"@@ -0,0 +1,265 @@\n+#!/usr/bin/python\n+# coding: latin-1\n+\n+\"\"\"\n+nat_scapy_tests.py: Rudimentary servers/clients for use in testing of the NAT.\n+Jonny Shipton, Cambridge University Computer Lab, July 2016\n+\n+Use of this source code is governed by the Apache 2.0 license; see LICENSE.\n+\n+This script is used in nat_topo.py in the testing of the NAT implementation.\n+The main reason for using Scapy is to be able to do things that may not be\n+possible with the OS network stack, such as sending packets during the TIME_WAIT state.\n+\"\"\"\n+\n+from scapy.all import *\n+from scapy.layers.inet import *\n+\n+# Values that need to be kept in sync with those in the wiring config:\n+# NOTE that all times are in seconds\n+tcp_inactivity_timeout = 20\n+tcp_time_wait_duration = 10\n+udp_inactivity_timeout= 200\n+\n+# The IP addresses of the nodes we use\n+serverhost = \"10.0.0.4\"\n+nathost = \"10.0.0.3\"\n+clienthost = \"192.168.1.10\"\n+\n+# Templates for iptables rules\n+iptables_rule_fmt = \"INPUT -p tcp --sport %d --dport %d -j DROP\"\n+iptables_add_rule_fmt = \"iptables -A %s\"\n+iptables_remove_rule_fmt = \"iptables -D %s\"\n+\n+# Data to be sent through the NAT\n+server_data = \"SERVER DATA\"\n+client_data = \"CLIENT DATA\"\n+\n+def run_server(serverport=12012, natport=35001):\n+    \"This should be run on the external host.\"\n+\n+    # Set up iptables rule to allow us exclusive access on our port\n+    iptables_rule = iptables_rule_fmt % (natport, serverport)\n+    print \"  server> $ %s\" % (iptables_add_rule_fmt % iptables_rule)\n+    subprocess.check_call(iptables_add_rule_fmt % iptables_rule, shell=True)\n+\n+    # We use the same IP layer and filter each time\n+    ip = IP(src=serverhost, dst=nathost)\n+    filter = \"tcp and host %s and port %d\" % (nathost, serverport)\n+\n+    # Wait for the connection to be initialised from the client\n+    print \"Waiting for connection from client\"\n+    syn = sniff(count=1, filter=filter)[0]\n+    # send Syn+Ack\n+    tcp_synack = TCP(sport=serverport, dport=natport, flags=\"SA\", options=[('MSS', 1460)])\n+    print \"Sending Syn+Ack\"\n+    send(ip/tcp_synack)\n+\n+    # Receive data and check if it is correct\n+    print \"Waiting for data from client\"\n+    datap = sniff(count=2, filter=filter)[1]\n+    print \"Received:\"\n+    datap.show()\n+    data = str(datap[TCP].payload)\n+    if (data == client_data):\n+        print \"Correct data received from the client.\"\n+    else:\n+        print \"WARNING: incorrect data received from the client: '%s'\" % data\n+\n+    # Wait for connection to be dropped\n+    print \"Sleeping to wait for the connection to be dropped by the NAT (reliant on tcp_inactivity_timeout=%ds)\" % tcp_inactivity_timeout\n+    time.sleep(tcp_inactivity_timeout + 2)\n+\n+    # Try sending data - should fail\n+    print \"Trying to send a packet to the client - should fail\"\n+    send(ip/TCP(sport=serverport, dport=natport, flags=\"\", options=[('MSS', 1460)])/\"FAIL PLEASE\")\n+\n+    # Remove iptables rule\n+    print \"  server> $ %s\" % (iptables_remove_rule_fmt % iptables_rule)\n+    subprocess.check_call(iptables_remove_rule_fmt % iptables_rule, shell=True)\n+\n+    if (data == client_data):\n+        return 0\n+    else:\n+        return 1\n+\n+def run_client(serverport=12012, clientport=12011):\n+    \"This should be run on the internal host.\"\n+\n+    # Set up iptables rule to allow us exclusive access on our port\n+    iptables_rule = iptables_rule_fmt % (serverport, clientport)\n+    print \"  client> $ %s\" % (iptables_add_rule_fmt % iptables_rule)\n+    subprocess.check_call(iptables_add_rule_fmt % iptables_rule, shell=True)\n+\n+    # We use the same IP layer and filter each time\n+    ip = IP(src=clienthost, dst=serverhost)\n+    filter = \"tcp and host %s and port %d\" % (serverhost, clientport)\n+\n+    # Establish connection to the server\n+    tcp_syn = TCP(sport=clientport, dport=serverport, flags=\"S\", options=[('MSS', 1460)])\n+    print \"Sending syn\"\n+    synack = sr1(ip/tcp_syn)[0]\n+    print \"Received:\"\n+    synack.show()\n+    # send Ack\n+    tcp_ack = TCP(sport=clientport, dport=serverport, flags=\"A\", options=[('MSS', 1460)])\n+    print \"Sending ack\"\n+    send(ip/tcp_ack)\n+\n+    # Send data\n+    print \"Sending data\"\n+    send(ip/TCP(sport=clientport, dport=serverport, flags=\"\")/client_data)\n+\n+    # Check we don't get another packet\n+    print \"Waiting to see if we get another packet\"\n+    rcv = sniff(count=1, timeout=tcp_inactivity_timeout + 5, filter=filter)\n+    if (len(rcv) != 0):\n+        print \"Received %d packets! Shouldn't have\" % len(rcv)\n+        rcv[0].show()\n+\n+    # Remove iptables rule\n+    print \"  client> $ %s\" % (iptables_remove_rule_fmt % iptables_rule)\n+    subprocess.check_call(iptables_remove_rule_fmt % iptables_rule, shell=True)\n+\n+\n+    if (len(rcv) != 0):\n+        return 1\n+    else:\n+        return 0\n+\n+def run_server2(serverport=12022, natport=35002):\n+    \"This should be run on the external host.\"\n+\n+    # Set up iptables rule to allow us exclusive access on our port\n+    iptables_rule = iptables_rule_fmt % (natport, serverport)\n+    print \"  server> $ %s\" % (iptables_add_rule_fmt % iptables_rule)\n+    subprocess.check_call(\"netcat -l %d &\" % serverport, shell=True)\n+    subprocess.check_call(iptables_add_rule_fmt % iptables_rule, shell=True)\n+\n+    # We use the same IP layer and filter each time\n+    ip = IP(src=serverhost, dst=nathost)\n+    filter = \"tcp and host %s and port %d\" % (nathost, serverport)\n+\n+    ## Set up and tear down connection\n+    # Wait for Syn\n+    print \"Waiting for Syn from client\"\n+    syn = sniff(count=1, filter=filter)\n+    # Syn+Ack\n+    print \"Replying with Syn+Ack\"\n+    ack = sr1(ip/TCP(sport=serverport,dport=natport,flags=\"SA\"))\n+    # Fin\n+    print \"Sending Fin\"\n+    finack = sr1(ip/TCP(sport=serverport,dport=natport,flags=\"FA\"))\n+    # Ack\n+    print \"Replying with Ack\"\n+    send(ip/TCP(sport=serverport,dport=natport,flags=\"A\"))\n+\n+    ## Now in TIME_WAIT\n+    print \"Sleeping to wait for the connection entry to be removed. (reliant on tcp_time_wait_duration=%ds)\" % tcp_time_wait_duration\n+    time.sleep(tcp_time_wait_duration + 1)\n+\n+    ## Should now be unable to use the connection\n+    # Send something\n+    time.sleep(1) # Wait to make sure the client has begun sniffing\n+    print \"Sending something - it shouldn't be received\"\n+    send(ip/TCP(sport=serverport,dport=natport,flags=\"A\")/\"FAIL PLEASE\")\n+    # Check we don't receive anything\n+    print \"Waiting to see if we receive anything\"\n+    rcv = sniff(count=1, timeout=2, filter=filter)\n+    if (len(rcv) != 0):\n+        print \"Received %d packets! Shouldn't have\" % len(rcv)\n+        rcv[0].show()\n+\n+    # Remove iptables rule\n+    print \"  server> $ %s\" % (iptables_remove_rule_fmt % iptables_rule)\n+    subprocess.check_call(iptables_remove_rule_fmt % iptables_rule, shell=True)\n+\n+    if (len(rcv) != 0):\n+        return 1\n+    else:\n+        return 0\n+\n+def run_client2(serverport=12022, clientport=12021):","path":"examples/nat_scapy_tests.py","position":182,"original_position":182,"commit_id":"fc467b965b85a5ff61b48d3f95592a9cbfc1856b","original_commit_id":"fc467b965b85a5ff61b48d3f95592a9cbfc1856b","user":{"login":"niksu","id":1102670,"avatar_url":"https://avatars.githubusercontent.com/u/1102670?v=3","gravatar_id":"","url":"https://api.github.com/users/niksu","html_url":"https://github.com/niksu","followers_url":"https://api.github.com/users/niksu/followers","following_url":"https://api.github.com/users/niksu/following{/other_user}","gists_url":"https://api.github.com/users/niksu/gists{/gist_id}","starred_url":"https://api.github.com/users/niksu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/niksu/subscriptions","organizations_url":"https://api.github.com/users/niksu/orgs","repos_url":"https://api.github.com/users/niksu/repos","events_url":"https://api.github.com/users/niksu/events{/privacy}","received_events_url":"https://api.github.com/users/niksu/received_events","type":"User","site_admin":false},"body":"How does this differ from `run_client`?","created_at":"2016-07-21T20:02:14Z","updated_at":"2016-07-21T20:02:14Z","html_url":"https://github.com/niksu/pax/pull/12#discussion_r71776593","pull_request_url":"https://api.github.com/repos/niksu/pax/pulls/12","_links":{"self":{"href":"https://api.github.com/repos/niksu/pax/pulls/comments/71776593"},"html":{"href":"https://github.com/niksu/pax/pull/12#discussion_r71776593"},"pull_request":{"href":"https://api.github.com/repos/niksu/pax/pulls/12"}}},"pull_request":{"url":"https://api.github.com/repos/niksu/pax/pulls/12","id":77640992,"html_url":"https://github.com/niksu/pax/pull/12","diff_url":"https://github.com/niksu/pax/pull/12.diff","patch_url":"https://github.com/niksu/pax/pull/12.patch","issue_url":"https://api.github.com/repos/niksu/pax/issues/12","number":12,"state":"open","locked":false,"title":"Refactor and extend NAT with UDP support","user":{"login":"TMVector","id":4268638,"avatar_url":"https://avatars.githubusercontent.com/u/4268638?v=3","gravatar_id":"","url":"https://api.github.com/users/TMVector","html_url":"https://github.com/TMVector","followers_url":"https://api.github.com/users/TMVector/followers","following_url":"https://api.github.com/users/TMVector/following{/other_user}","gists_url":"https://api.github.com/users/TMVector/gists{/gist_id}","starred_url":"https://api.github.com/users/TMVector/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TMVector/subscriptions","organizations_url":"https://api.github.com/users/TMVector/orgs","repos_url":"https://api.github.com/users/TMVector/repos","events_url":"https://api.github.com/users/TMVector/events{/privacy}","received_events_url":"https://api.github.com/users/TMVector/received_events","type":"User","site_admin":false},"body":"This PR is a neatened and improved version of [#9](https://github.com/niksu/pax/pull/9).\r\n\r\nRefactor the NAT to reflect the approach of an applications software engineer. Also add support for UDP, timeouts, TCP state, and TIME_WAIT.","created_at":"2016-07-15T16:16:33Z","updated_at":"2016-07-21T20:02:14Z","closed_at":null,"merged_at":null,"merge_commit_sha":"16abbc766cee086899c2fdf22e6d325fe83d2088","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/niksu/pax/pulls/12/commits","review_comments_url":"https://api.github.com/repos/niksu/pax/pulls/12/comments","review_comment_url":"https://api.github.com/repos/niksu/pax/pulls/comments{/number}","comments_url":"https://api.github.com/repos/niksu/pax/issues/12/comments","statuses_url":"https://api.github.com/repos/niksu/pax/statuses/fc467b965b85a5ff61b48d3f95592a9cbfc1856b","head":{"label":"TMVector:refactor-nat","ref":"refactor-nat","sha":"fc467b965b85a5ff61b48d3f95592a9cbfc1856b","user":{"login":"TMVector","id":4268638,"avatar_url":"https://avatars.githubusercontent.com/u/4268638?v=3","gravatar_id":"","url":"https://api.github.com/users/TMVector","html_url":"https://github.com/TMVector","followers_url":"https://api.github.com/users/TMVector/followers","following_url":"https://api.github.com/users/TMVector/following{/other_user}","gists_url":"https://api.github.com/users/TMVector/gists{/gist_id}","starred_url":"https://api.github.com/users/TMVector/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TMVector/subscriptions","organizations_url":"https://api.github.com/users/TMVector/orgs","repos_url":"https://api.github.com/users/TMVector/repos","events_url":"https://api.github.com/users/TMVector/events{/privacy}","received_events_url":"https://api.github.com/users/TMVector/received_events","type":"User","site_admin":false},"repo":{"id":61544345,"name":"pax","full_name":"TMVector/pax","owner":{"login":"TMVector","id":4268638,"avatar_url":"https://avatars.githubusercontent.com/u/4268638?v=3","gravatar_id":"","url":"https://api.github.com/users/TMVector","html_url":"https://github.com/TMVector","followers_url":"https://api.github.com/users/TMVector/followers","following_url":"https://api.github.com/users/TMVector/following{/other_user}","gists_url":"https://api.github.com/users/TMVector/gists{/gist_id}","starred_url":"https://api.github.com/users/TMVector/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TMVector/subscriptions","organizations_url":"https://api.github.com/users/TMVector/orgs","repos_url":"https://api.github.com/users/TMVector/repos","events_url":"https://api.github.com/users/TMVector/events{/privacy}","received_events_url":"https://api.github.com/users/TMVector/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/TMVector/pax","description":"","fork":true,"url":"https://api.github.com/repos/TMVector/pax","forks_url":"https://api.github.com/repos/TMVector/pax/forks","keys_url":"https://api.github.com/repos/TMVector/pax/keys{/key_id}","collaborators_url":"https://api.github.com/repos/TMVector/pax/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/TMVector/pax/teams","hooks_url":"https://api.github.com/repos/TMVector/pax/hooks","issue_events_url":"https://api.github.com/repos/TMVector/pax/issues/events{/number}","events_url":"https://api.github.com/repos/TMVector/pax/events","assignees_url":"https://api.github.com/repos/TMVector/pax/assignees{/user}","branches_url":"https://api.github.com/repos/TMVector/pax/branches{/branch}","tags_url":"https://api.github.com/repos/TMVector/pax/tags","blobs_url":"https://api.github.com/repos/TMVector/pax/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/TMVector/pax/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/TMVector/pax/git/refs{/sha}","trees_url":"https://api.github.com/repos/TMVector/pax/git/trees{/sha}","statuses_url":"https://api.github.com/repos/TMVector/pax/statuses/{sha}","languages_url":"https://api.github.com/repos/TMVector/pax/languages","stargazers_url":"https://api.github.com/repos/TMVector/pax/stargazers","contributors_url":"https://api.github.com/repos/TMVector/pax/contributors","subscribers_url":"https://api.github.com/repos/TMVector/pax/subscribers","subscription_url":"https://api.github.com/repos/TMVector/pax/subscription","commits_url":"https://api.github.com/repos/TMVector/pax/commits{/sha}","git_commits_url":"https://api.github.com/repos/TMVector/pax/git/commits{/sha}","comments_url":"https://api.github.com/repos/TMVector/pax/comments{/number}","issue_comment_url":"https://api.github.com/repos/TMVector/pax/issues/comments{/number}","contents_url":"https://api.github.com/repos/TMVector/pax/contents/{+path}","compare_url":"https://api.github.com/repos/TMVector/pax/compare/{base}...{head}","merges_url":"https://api.github.com/repos/TMVector/pax/merges","archive_url":"https://api.github.com/repos/TMVector/pax/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/TMVector/pax/downloads","issues_url":"https://api.github.com/repos/TMVector/pax/issues{/number}","pulls_url":"https://api.github.com/repos/TMVector/pax/pulls{/number}","milestones_url":"https://api.github.com/repos/TMVector/pax/milestones{/number}","notifications_url":"https://api.github.com/repos/TMVector/pax/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/TMVector/pax/labels{/name}","releases_url":"https://api.github.com/repos/TMVector/pax/releases{/id}","deployments_url":"https://api.github.com/repos/TMVector/pax/deployments","created_at":"2016-06-20T11:58:19Z","updated_at":"2016-06-28T19:38:38Z","pushed_at":"2016-07-20T12:07:51Z","git_url":"git://github.com/TMVector/pax.git","ssh_url":"git@github.com:TMVector/pax.git","clone_url":"https://github.com/TMVector/pax.git","svn_url":"https://github.com/TMVector/pax","homepage":null,"size":208,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"niksu:master","ref":"master","sha":"127108813c188c11f01b5cd05a13b412790a5fc5","user":{"login":"niksu","id":1102670,"avatar_url":"https://avatars.githubusercontent.com/u/1102670?v=3","gravatar_id":"","url":"https://api.github.com/users/niksu","html_url":"https://github.com/niksu","followers_url":"https://api.github.com/users/niksu/followers","following_url":"https://api.github.com/users/niksu/following{/other_user}","gists_url":"https://api.github.com/users/niksu/gists{/gist_id}","starred_url":"https://api.github.com/users/niksu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/niksu/subscriptions","organizations_url":"https://api.github.com/users/niksu/orgs","repos_url":"https://api.github.com/users/niksu/repos","events_url":"https://api.github.com/users/niksu/events{/privacy}","received_events_url":"https://api.github.com/users/niksu/received_events","type":"User","site_admin":false},"repo":{"id":61248237,"name":"pax","full_name":"niksu/pax","owner":{"login":"niksu","id":1102670,"avatar_url":"https://avatars.githubusercontent.com/u/1102670?v=3","gravatar_id":"","url":"https://api.github.com/users/niksu","html_url":"https://github.com/niksu","followers_url":"https://api.github.com/users/niksu/followers","following_url":"https://api.github.com/users/niksu/following{/other_user}","gists_url":"https://api.github.com/users/niksu/gists{/gist_id}","starred_url":"https://api.github.com/users/niksu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/niksu/subscriptions","organizations_url":"https://api.github.com/users/niksu/orgs","repos_url":"https://api.github.com/users/niksu/repos","events_url":"https://api.github.com/users/niksu/events{/privacy}","received_events_url":"https://api.github.com/users/niksu/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/niksu/pax","description":"Framework for prototyping network elements","fork":false,"url":"https://api.github.com/repos/niksu/pax","forks_url":"https://api.github.com/repos/niksu/pax/forks","keys_url":"https://api.github.com/repos/niksu/pax/keys{/key_id}","collaborators_url":"https://api.github.com/repos/niksu/pax/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/niksu/pax/teams","hooks_url":"https://api.github.com/repos/niksu/pax/hooks","issue_events_url":"https://api.github.com/repos/niksu/pax/issues/events{/number}","events_url":"https://api.github.com/repos/niksu/pax/events","assignees_url":"https://api.github.com/repos/niksu/pax/assignees{/user}","branches_url":"https://api.github.com/repos/niksu/pax/branches{/branch}","tags_url":"https://api.github.com/repos/niksu/pax/tags","blobs_url":"https://api.github.com/repos/niksu/pax/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/niksu/pax/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/niksu/pax/git/refs{/sha}","trees_url":"https://api.github.com/repos/niksu/pax/git/trees{/sha}","statuses_url":"https://api.github.com/repos/niksu/pax/statuses/{sha}","languages_url":"https://api.github.com/repos/niksu/pax/languages","stargazers_url":"https://api.github.com/repos/niksu/pax/stargazers","contributors_url":"https://api.github.com/repos/niksu/pax/contributors","subscribers_url":"https://api.github.com/repos/niksu/pax/subscribers","subscription_url":"https://api.github.com/repos/niksu/pax/subscription","commits_url":"https://api.github.com/repos/niksu/pax/commits{/sha}","git_commits_url":"https://api.github.com/repos/niksu/pax/git/commits{/sha}","comments_url":"https://api.github.com/repos/niksu/pax/comments{/number}","issue_comment_url":"https://api.github.com/repos/niksu/pax/issues/comments{/number}","contents_url":"https://api.github.com/repos/niksu/pax/contents/{+path}","compare_url":"https://api.github.com/repos/niksu/pax/compare/{base}...{head}","merges_url":"https://api.github.com/repos/niksu/pax/merges","archive_url":"https://api.github.com/repos/niksu/pax/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/niksu/pax/downloads","issues_url":"https://api.github.com/repos/niksu/pax/issues{/number}","pulls_url":"https://api.github.com/repos/niksu/pax/pulls{/number}","milestones_url":"https://api.github.com/repos/niksu/pax/milestones{/number}","notifications_url":"https://api.github.com/repos/niksu/pax/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/niksu/pax/labels{/name}","releases_url":"https://api.github.com/repos/niksu/pax/releases{/id}","deployments_url":"https://api.github.com/repos/niksu/pax/deployments","created_at":"2016-06-15T23:43:36Z","updated_at":"2016-06-27T05:34:46Z","pushed_at":"2016-07-21T14:47:14Z","git_url":"git://github.com/niksu/pax.git","ssh_url":"git@github.com:niksu/pax.git","clone_url":"https://github.com/niksu/pax.git","svn_url":"https://github.com/niksu/pax","homepage":"","size":220,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":9,"forks":1,"open_issues":9,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/niksu/pax/pulls/12"},"html":{"href":"https://github.com/niksu/pax/pull/12"},"issue":{"href":"https://api.github.com/repos/niksu/pax/issues/12"},"comments":{"href":"https://api.github.com/repos/niksu/pax/issues/12/comments"},"review_comments":{"href":"https://api.github.com/repos/niksu/pax/pulls/12/comments"},"review_comment":{"href":"https://api.github.com/repos/niksu/pax/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/niksu/pax/pulls/12/commits"},"statuses":{"href":"https://api.github.com/repos/niksu/pax/statuses/fc467b965b85a5ff61b48d3f95592a9cbfc1856b"}}}}
{"actor":{"display_login":"niksu"}}