Skip to content

Instantly share code, notes, and snippets.

@fnordomat
Last active September 7, 2021 07:34
Show Gist options
  • Save fnordomat/40860a59162b2658324dbf666b10538c to your computer and use it in GitHub Desktop.
Save fnordomat/40860a59162b2658324dbf666b10538c to your computer and use it in GitHub Desktop.
Automatic negotiation of a captive portal: connect to m3connect wifi in some Accor group hotels without having to jump through hoops.
#!/bin/bash
# Accor group hotels offer "free wifi" (ESSID: "m3connect") service
# with internet access (with paid options for higher transfer rates).
#
# This takes care of the m3connect captive portal.
#
# Please drop me a note if it stops working, is insecure etc.
#
# very basic, something like this worked for me
curl --stderr - --trace - -v -L -A '' http://google.com | tee step0001
curl --stderr - --trace - -v -L -A '' -c kookie.jar https://portal.m3connect.de/en/login/free | tee step0002
cat kookie.jar
PHPSESSID=$(grep PHPSESSID kookie.jar | perl -ne '/([A-Za-z0-9]*)$/; print $1;')
curl --stderr - --trace - --post301 --post302 --post303 -v -L -A 'Mozilla/5.0' -e 'https://portal.m3connect.de/en/login/free' -b "PHPSESSID=${PHPSESSID}" -F submit=Register -F "registration[tariff]=707" -F "registration[terms]=1" https://portal.m3connect.de/en/register/free | tee step0003
@humaita-github
Copy link

Hi, thank you very much for the feedback. I tested your newest script. Unfortunately, it doenst fully work yet, see error detailed output below.

However, if I comment out lines 90 and 91 in the newest script it works a little bit better (I still need to run it a few times until it succesfully authenticates).

let's go
request GET http://detectportal.firefox.com/success.txt
request headers: {'User-Agent': 'Mozilla/5.0', 'Cookie': ''}
response headers: HTTPHeaderDict({'cache-control': 'max-age=0, private, must-revalidate', 'content-length': '441', 'content-type': 'text/html; charset=utf-8', 'date': 'Wed, 02 Dec 2020 21:28:25 GMT', 'location': 'https://210.rdr.conn4.com/ident?client_ip=10.22.57.66&client_mac=0A000A163942&site_id=210&signature=d2edb1b884f2b030c67ee5fe3e4daec068b46d1c90e4e68d07a66e9feb141924&loggedin=0&remembered_mac=0', 'server': 'Cowboy'})
redirect: https://210.rdr.conn4.com/ident?client_ip=10.22.57.66&client_mac=0A000A163942&site_id=210&signature=d2edb1b884f2b030c67ee5fe3e4daec068b46d1c90e4e68d07a66e9feb141924&loggedin=0&remembered_mac=0
b'<!doctype html>\n<html>\n\n <head>\n <title>Redirecting ....</title>\n <meta name="viewport" content="width=device-width, initial-scale=1">\n <meta http-equiv="refresh" content="1; URL=https://210.rdr.conn4.com/ident?client_ip=10.22.57.66&client_mac=0A000A163942&site_id=210&signature=d2edb1b884f2b030c67ee5fe3e4daec068b46d1c90e4e68d07a66e9feb141924&loggedin=0&remembered_mac=0">\n </head>\n <body>\n Redirecting ...\n </body>\n</html>\n'
`request GET https://210.rdr.conn4.com/ident?client_ip=10.22.57.66&client_mac=0A000A163942&site_id=210&signature=d2edb1b884f2b030c67ee5fe3e4daec068b46d1c90e4e68d07a66e9feb141924&loggedin=0&remembered_mac=0` `request headers: {'User-Agent': 'Mozilla/5.0', 'Cookie': ''}` `response headers: HTTPHeaderDict({'Server': 'm3connect', 'Date': 'Wed, 02 Dec 2020 21:28:25 GMT', 'Content-Type': 'text/html; charset=UTF-8', 'Content-Length': '0', 'Connection': 'keep-alive', 'Set-Cookie': 'ngx_conn4_portal=96508d6209a17693f0379bb61abe725b; expires=Wed, 02-Dec-20 21:58:25 GMT; max-age=1800; path=/, himalaya-site-ident=SFNJKk86MzQ6Ik0zXEhpbWFsYXlhXFNoYXJlZFxTaXRlSWRlbnRcVG9rZW4iOjk6e3M6MTM6IgAqAE1BQ0FkZHJlc3MiO3M6MTI6IjBBMDAwQTE2Mzk0MiI7czoxOToiACoAZXh0ZW5kZWRMaWZldGltZSI7YjowO3M6MTI6IgAqAElQQWRkcmVzcyI7czoxMToiMTAuMjIuNTcuNjYiO3M6MTY6IgAqAHJlbW90ZUFkZHJlc3MiO3M6MTM6IjE4NS4yMDIuMzIuMjYiO3M6OToiACoAbm9kZUlkIjtOO3M6OToiACoAc2l0ZUlkIjtpOjIxMDtzOjIyOiIAKgBjb250ZW50UmVwb3NpdG9yeUlkIjtOO3M6NzoiACoAdXJscyI7YTowOnt9czoxMDoiACoAY3JlYXRlZCI7Tzo4OiJEYXRlVGltZSI6Mzp7czo0OiJkYXRlIjtzOjI2OiIyMDIwLTEyLTAyIDIxOjI4OjI1LjAwMDAwMCI7czoxMzoidGltZXpvbmVfdHlwZSI7aTozO3M6ODoidGltZXpvbmUiO3M6MzoiVVRDIjt9fXwyMmMzNmYyOWI5ZDRiYjBiNmI0YTQ2MDU3NTBiMTQwZjM1ZjM5NTFhNmZiNzc2ZGFhNjlkOTFhODJlYjUyY2Qy; expires=Wed, 02-Dec-2020 21:58:25 GMT; Max-Age=1800; path=/', 'Location': 'https://210.rdr.conn4.com/#', 'Strict-Transport-Security': 'max-age=31415926', 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'SAMEORIGIN', 'X-XSS-Protection': '1; mode=block', 'X-DNS-Prefetch-Control': 'off'})` `redirect: https://210.rdr.conn4.com/#` `setting cookie ngx_conn4_portal to 96508d6209a17693f0379bb61abe725b` `setting cookie himalaya-site-ident to SFNJKk86MzQ6Ik0zXEhpbWFsYXlhXFNoYXJlZFxTaXRlSWRlbnRcVG9rZW4iOjk6e3M6MTM6IgAqAE1BQ0FkZHJlc3MiO3M6MTI6IjBBMDAwQTE2Mzk0MiI7czoxOToiACoAZXh0ZW5kZWRMaWZldGltZSI7YjowO3M6MTI6IgAqAElQQWRkcmVzcyI7czoxMToiMTAuMjIuNTcuNjYiO3M6MTY6IgAqAHJlbW90ZUFkZHJlc3MiO3M6MTM6IjE4NS4yMDIuMzIuMjYiO3M6OToiACoAbm9kZUlkIjtOO3M6OToiACoAc2l0ZUlkIjtpOjIxMDtzOjIyOiIAKgBjb250ZW50UmVwb3NpdG9yeUlkIjtOO3M6NzoiACoAdXJscyI7YTowOnt9czoxMDoiACoAY3JlYXRlZCI7Tzo4OiJEYXRlVGltZSI6Mzp7czo0OiJkYXRlIjtzOjI2OiIyMDIwLTEyLTAyIDIxOjI4OjI1LjAwMDAwMCI7czoxMzoidGltZXpvbmVfdHlwZSI7aTozO3M6ODoidGltZXpvbmUiO3M6MzoiVVRDIjt9fXwyMmMzNmYyOWI5ZDRiYjBiNmI0YTQ2MDU3NTBiMTQwZjM1ZjM5NTFhNmZiNzc2ZGFhNjlkOTFhODJlYjUyY2Qy` `himalaya-site-ident: b'HSI*O:34:"M3\\Himalaya\\Shared\\SiteIdent\\Token":9:{s:13:"\x00*\x00MACAddress";s:12:"0A000A163942";s:19:"\x00*\x00extendedLifetime";b:0;s:12:"\x00*\x00IPAddress";s:11:"10.22.57.66";s:16:"\x00*\x00remoteAddress";s:13:"185.202.32.26";s:9:"\x00*\x00nodeId";N;s:9:"\x00*\x00siteId";i:210;s:22:"\x00*\x00contentRepositoryId";N;s:7:"\x00*\x00urls";a:0:{}s:10:"\x00*\x00created";O:8:"DateTime":3:{s:4:"date";s:26:"2020-12-02 21:28:25.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:3:"UTC";}}|22c36f29b9d4bb0b6b4a4605750b140f35f3951a6fb776daa69d91a82eb52cd2'` `b''`
request GET https://210.rdr.conn4.com/#
request headers: {'User-Agent': 'Mozilla/5.0', 'Cookie': 'ngx_conn4_portal=96508d6209a17693f0379bb61abe725b; himalaya-site-ident=SFNJKk86MzQ6Ik0zXEhpbWFsYXlhXFNoYXJlZFxTaXRlSWRlbnRcVG9rZW4iOjk6e3M6MTM6IgAqAE1BQ0FkZHJlc3MiO3M6MTI6IjBBMDAwQTE2Mzk0MiI7czoxOToiACoAZXh0ZW5kZWRMaWZldGltZSI7YjowO3M6MTI6IgAqAElQQWRkcmVzcyI7czoxMToiMTAuMjIuNTcuNjYiO3M6MTY6IgAqAHJlbW90ZUFkZHJlc3MiO3M6MTM6IjE4NS4yMDIuMzIuMjYiO3M6OToiACoAbm9kZUlkIjtOO3M6OToiACoAc2l0ZUlkIjtpOjIxMDtzOjIyOiIAKgBjb250ZW50UmVwb3NpdG9yeUlkIjtOO3M6NzoiACoAdXJscyI7YTowOnt9czoxMDoiACoAY3JlYXRlZCI7Tzo4OiJEYXRlVGltZSI6Mzp7czo0OiJkYXRlIjtzOjI2OiIyMDIwLTEyLTAyIDIxOjI4OjI1LjAwMDAwMCI7czoxMzoidGltZXpvbmVfdHlwZSI7aTozO3M6ODoidGltZXpvbmUiO3M6MzoiVVRDIjt9fXwyMmMzNmYyOWI5ZDRiYjBiNmI0YTQ2MDU3NTBiMTQwZjM1ZjM5NTFhNmZiNzc2ZGFhNjlkOTFhODJlYjUyY2Qy'}
response headers: HTTPHeaderDict({'Server': 'm3connect', 'Date': 'Wed, 02 Dec 2020 21:28:25 GMT', 'Content-Type': 'text/html; charset=utf-8', 'Content-Length': '7074', 'Connection': 'keep-alive', 'Set-Cookie': 'ngx_conn4_portal=96508d6209a17693f0379bb61abe725b; expires=Wed, 02-Dec-20 21:58:25 GMT; max-age=1800; path=/', 'Strict-Transport-Security': 'max-age=31415926', 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'SAMEORIGIN', 'X-XSS-Protection': '1; mode=block', 'X-DNS-Prefetch-Control': 'off'})
replacing cookie ngx_conn4_portal with 96508d6209a17693f0379bb61abe725b
b'<!DOCTYPE html>\n<html xmlns="http://www.w3.org/1999/xhtml" id="no-js">\n <head>\n <script>\n var scenename = \'sceneplayer\';\n if (typeof scenename === \'undefined\') {\n var scenename = \'undefined\';\n}\n\nfunction logError(error) {\n var oReq = new XMLHttpRequest();\n oReq.open("POST", "/admon-assets/log.php?channel=clienterror", true);\n oReq.setRequestHeader(\'Content-type\', \'application/x-www-form-urlencoded\');\n oReq.send("type=" + error.type\n + "&msg=" + error.message\n + " | module=" + scenename\n + " | file=" + error.filename\n + " | line=" + error.lineno\n + " | col=" + error.colno\n );\n}\n\nwindow.addEventListener(\'error\', logError);\n </script>\n\n <script type="text/javascript">with(document.documentElement){id=id.replace(\'no-\',\'\');}</script>\n <style>body{margin:0}object{position:absolute;top:0;left:0;opacity:0;z-index:100}.fullscreen{width:100%;height:100%;position:absolute;border:0}.fade-out{opacity:0}.fade-in{opacity:1;-webkit-transition:opacity 1500ms ease-out;-moz-transition:opacity 1500ms ease-out;-o-transition:opacity 1500ms ease-out;transition:opacity 1500ms ease-out}.message{background:rgba(0,0,0,.8);position:absolute;bottom:0;left:0;right:0;z-index:1000 !important;padding:1em;text-align:center;font-size:32px;color:#fff}.hidden,#no-js #_loading_indicator,#_scene_volume,#_standby_overlay{display:none}.error{background-color:#eee;z-index:200}.error>div{width:500px;text-align:center;margin:-5em auto 0;position:relative;top:50%;font-size:24px;font-family:Helvetica,Arial,sans-serif}#_scene_content>iframe.ios-fix{width:1px;min-width:100%;*width:100%;overflow:auto;height:100%;overflow-y:scroll;-webkit-overflow-scrolling:touch}#_loading_indicator{position:fixed;z-index:10000;bottom:0;top:0;left:0;right:0}#_loading_indicator>.loading--simple{position:absolute;bottom:.6rem;right:.8rem;font-size:.9rem;padding:.5rem;border-radius:.3rem;font-family:sans-serif;color:black;background-color:rgba(255,255,255,.9)}\n</style>\n\n <style id="_scene_custom_style" type="text/css"></style>\n\n <meta http-equiv="X-UA-Compatible" content="IE=edge"/>\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n\n \n </head>\n\n <body>\n <!--\n <?xml version="1.0" encoding="UTF-8"?>\n <WISPAccessGatewayParam xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.acmewisp.com/WISPAccessGatewayParam.xsd">\n <Redirect>\n <AccessProcedure>1.0</AccessProcedure>\n <AccessLocation>12</AccessLocation>\n <LocationName>CONN4</LocationName>\n <LoginURL>https://210.rdr.conn4.com/wbs/de/roaming/return/</LoginURL>\n <MessageType>100</MessageType>\n <ResponseCode>0</ResponseCode>\n </Redirect>\n </WISPAccessGatewayParam>\n -->\n\n <noscript>\n <div class="error fullscreen">\n <div>\n <p>Please enable JavaScript to continue.</p>\n </div>\n </div>\n </noscript>\n\n <div id="_error" class="error hidden fullscreen">\n <div>\n <h1>Error <span class="js-error-code">601</span></h1>\n <p>Need assistance?</p>\n <p>Wi-Fi-Hotline: +49 (0) 241 / 705 39 605<br/>\n <span style="font-size: 50%">(at local tariff throughout Germany)</span></p>\n </div>\n </div>\n\n \n <div id="_scene_content" data-channel="">\n </div>\n\n <div id="_loading_indicator" class="loading--initial">\n <div class="loading--simple">\n Loading ...\n </div>\n </div>\n\n \n <script src="/cache/js-file-e552c72faa03fb9c5ea859701ce5304e8feb8e0f-j-a578d89915ec98c5314bf279b2b6766c.js" type="text/javascript"></script>\n <script type="text/javascript">\n (function() {\n if (!location.search) {\n return;\n }\n\n var url = location.href.replace(location.search, \'\');\n if (history && history.replaceState) {\n history.replaceState(history.state || {}, document.title, url);\n } else {\n location.href = url;\n }\n })();\n </script>\n <script type="text/javascript">\n conn4.deviceConfiguration = false;\n\n conn4.log = $.noop;\n \n// conn4.recorder = new conn4.LogRecorder({log: conn4.log});\n// conn4.record = conn4.recorder.record;\n conn4.record = function() {};\n\n conn4.eventTracker = new conn4.EventTracker({\n logger: conn4.logger\n });\n conn4.trackEvent = conn4.eventTracker.track;\n \n conn4.serverdate = new conn4.ServerDate({\n initializationTs: 1606944505621,\n log: conn4.log\n });\n var ServerDate = function () {\n return new Date(ServerDate.now());\n };\n ServerDate.now = function() {\n return conn4.serverdate.getMilliseconds();\n };\n\n \n \n conn4.hotspot = conn4.hotspot || {};\n conn4.hotspot.wbsToken = {"token":"SFdBKk86MzU6Ik0zXEhpbWFsYXlhXFNoYXJlZFxXQlNBcGlBdXRoXFRva2VuIjo1OntzOjk6IgAqAHNpdGVJZCI7aToyMTA7czoxNjoiACoAcmVtb3RlQWRkcmVzcyI7czoxMToiMTAuMjIuNTcuNjYiO3M6MTM6IgAqAG1hY0FkZHJlc3MiO3M6MTI6IjBBMDAwQTE2Mzk0MiI7czoxMDoiACoAY3JlYXRlZCI7Tzo4OiJEYXRlVGltZSI6Mzp7czo0OiJkYXRlIjtzOjI2OiIyMDIwLTEyLTAyIDIxOjI4OjI1LjAwMDAwMCI7czoxMzoidGltZXpvbmVfdHlwZSI7aTozO3M6ODoidGltZXpvbmUiO3M6MzoiVVRDIjt9czo5OiIAKgBvcmlnaW4iO3M6MjU6Imh0dHBzOi8vMjEwLnJkci5jb25uNC5jb20iO318NmRmZDk4OWU0OGVmYjA3ZGU3MWVkZmYxYWUzMzdkYjRlOTQ4OWFkZWZjOTUyODU0MDE5NWE0MjJmYTYxMTJiZA==","urls":{"grant_url":null,"continue_url":null}};\n setTimeout(function() {\n conn4.hotspot.wbsToken = undefined;\n }, 118 * 60 * 1000); \n $(_.partial(conn4.startSceneLoader, {\n log: conn4.log,\n trackEvent: conn4.trackEvent,\n settings: {"sceneLoaderAssertLoaded":true,"sceneLoaderTimeoutLimit":2}\n,\n schedule: {"token":{"site":210,"group":"desktop","mac":"0A000A163942"},"site_title":"","url_version":1,"scene_template":"https:\\/\\/210.rdr.conn4.com\\/scenes\\/{id}\\/","fallback":"https:\\/\\/210.rdr.conn4.com\\/admon-assets\\/fallback.html","error_404":"https:\\/\\/210.rdr.conn4.com\\/admon\\/404","initialization_ts":1606944505,"events":[{"time":"1984-11-17 00:00:00","seq":100,"type":"view","payload":{"type":"scene","data":{"id":"5jx9ZrGe72eI0l4n","module":"html-page-scene-wbs-new","variant":"default"}}},{"time":"1984-11-17 00:00:00","seq":200,"type":"campaign","payload":null}],"playlists":[],"navigations":[]}\n }));\n </script>\n </body>\n</html>\n'
``
request GET None
`request headers: {'User-Agent': 'Mozilla/5.0', 'Cookie': 'ngx_conn4_portal=96508d6209a17693f0379bb61abe725b; himalaya-site-ident=SFNJKk86MzQ6Ik0zXEhpbWFsYXlhXFNoYXJlZFxTaXRlSWRlbnRcVG9rZW4iOjk6e3M6MTM6IgAqAE1BQ0FkZHJlc3MiO3M6MTI6IjBBMDAwQTE2Mzk0MiI7czoxOToiACoAZXh0ZW5kZWRMaWZldGltZSI7YjowO3M6MTI6IgAqAElQQWRkcmVzcyI7czoxMToiMTAuMjIuNTcuNjYiO3M6MTY6IgAqAHJlbW90ZUFkZHJlc3MiO3M6MTM6IjE4NS4yMDIuMzIuMjYiO3M6OToiACoAbm9kZUlkIjtOO3M6OToiACoAc2l0ZUlkIjtpOjIxMDtzOjIyOiIAKgBjb250ZW50UmVwb3NpdG9yeUlkIjtOO3M6NzoiACoAdXJscyI7YTowOnt9czoxMDoiACoAY3JlYXRlZCI7Tzo4OiJEYXRlVGltZSI6Mzp7czo0OiJkYXRlIjtzOjI2OiIyMDIwLTEyLTAyIDIxOjI4OjI1LjAwMDAwMCI7czoxMzoidGltZXpvbmVfdHlwZSI7aTozO3M6ODoidGltZXpvbmUiO3M6MzoiVVRDIjt9fXwyMmMzNmYyOWI5ZDRiYjBiNmI0YTQ2MDU3NTBiMTQwZjM1ZjM5NTFhNmZiNzc2ZGFhNjlkOTFhODJlYjUyY2Qy'}`
`Traceback (most recent call last):`
` File "./m34.py", line 95, in `
` f3 = foo.perform_get(url)`
` File "./m34.py", line 76, in perform_get`
` f = pool.request(method='GET', url=url, headers=headers, redirect=redirect)`
` File "/usr/lib/python3/dist-packages/urllib3/request.py", line 75, in request`
` return self.request_encode_url(`
` File "/usr/lib/python3/dist-packages/urllib3/request.py", line 97, in request_encode_url`
` return self.urlopen(method, url, **extra_kw)`
` File "/usr/lib/python3/dist-packages/urllib3/poolmanager.py", line 319, in urlopen`
` conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme)`
` File "/usr/lib/python3/dist-packages/urllib3/poolmanager.py", line 225, in connection_from_host`
` raise LocationValueError("No host specified.")`
`urllib3.exceptions.LocationValueError: No host specified.`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment