Autor Thema: [patch] [HUEBridge] proxy support for websockets  (Gelesen 293 mal)

Offline ruff

  • Newbie
  • Beiträge: 2
[patch] [HUEBridge] proxy support for websockets
« am: 03 Oktober 2021, 23:14:16 »
Hi,
I'm using deconz+conbee2 but in zero-trust setup hence all networks interfaces are firewalled off and proxy whitelist is used for web policy. And while fhem speaks ok via proxy for rest api, websockets are failing due to trying to make direct connection bypassing proxy.
Hence I came up with this little patch to make use of HttpUtils for socket opening which enables proxy support.

Index: FHEM/30_HUEBridge.pm
===================================================================
--- FHEM/30_HUEBridge.pm        (Revision 25044)
+++ FHEM/30_HUEBridge.pm        (Arbeitskopie)
@@ -371,6 +371,43 @@
   HUEBridge_closeWebsocket($hash);
 
   my ($host,undef) = split(':',$hash->{host},2);
+
+  if( my $proxy = AttrVal("global", "proxy", undef) ) {
+    $hash->{url} = "http://$host:$hash->{websocketport}/";
+    $hash->{noConnect2} = 1;
+    $hash->{callback} = sub($) {
+      $hash->{conn}->blocking(1);
+      my $pw = AttrVal("global", "proxyAuth", "");                           
+      $pw = "Proxy-Authorization: Basic $pw\r\n" if($pw);                     
+      my $hdr = "CONNECT $host:$hash->{websocketport} HTTP/1.0\r\nUser-Agent: fhem\r\n$pw\r\n";                               
+      syswrite $hash->{conn}, $hdr;
+      my $buf;
+      my $len = sysread($hash->{conn},$buf,65536);
+      if(!defined($len) || $len <= 0 || $buf !~ m/HTTP.*200/) {
+        HttpUtils_Close($hash);
+        Log3 $name, 2, "$name: failed to open websocket via proxy";
+        return;
+      }
+
+      $hash->{CD} = $hash->{conn};
+      delete $hash->{conn};
+      $hash->{PORT} = $hash->{websocketport};
+      my $ret = "GET ws://$host:$hash->{websocketport} HTTP/1.1\r\n";
+      $ret .= HUEBridge_hash2header( {                  'Host' => "$host:$hash->{websocketport}",
+                                                     'Upgrade' => 'websocket',
+                                                  'Connection' => 'Upgrade',
+                                                      'Pragma' => 'no-cache',
+                                               'Cache-Control' => 'no-cache',
+                                           'Sec-WebSocket-Key' => 'RkhFTQ==',
+                                       'Sec-WebSocket-Version' => '13',
+                                     } );
+      $ret .= "\r\n";
+      syswrite($hash->{CD}, $ret );
+    };
+    HttpUtils_Connect($hash);
+    return;
+  }
+
   if( my $socket = IO::Socket::INET->new(PeerAddr=>"$host:$hash->{websocketport}", Timeout=>2, Blocking=>1, ReuseAddr=>1) ) {
     $hash->{CD}    = $socket;
     $hash->{FD}    = $socket->fileno();

wiki only mentions this channel for patch submission so here we are.

Offline ruff

  • Newbie
  • Beiträge: 2
Antw:[patch] [HUEBridge] proxy support for websockets
« Antwort #1 am: 04 Oktober 2021, 08:07:03 »
Sorry just realized it wasn't the latest version of the patch, here's the latest (and tested) one:
Index: FHEM/30_HUEBridge.pm
===================================================================
--- FHEM/30_HUEBridge.pm        (Revision 25044)
+++ FHEM/30_HUEBridge.pm        (Arbeitskopie)
@@ -371,6 +371,44 @@
   HUEBridge_closeWebsocket($hash);
 
   my ($host,undef) = split(':',$hash->{host},2);
+
+  if( my $proxy = AttrVal("global", "proxy", undef) ) {
+    my $h = { %$hash };
+    $h->{url} = "http://$host:$hash->{websocketport}/";
+    $h->{noConn2} = 1;
+    $h->{callback} = sub($) {
+      my ($h) = @_;
+      $h->{conn}->blocking(1);
+      my $pw = AttrVal("global", "proxyAuth", "");                           
+      $pw = "Proxy-Authorization: Basic $pw\r\n" if($pw);                     
+      my $hdr = "CONNECT $host:$hash->{websocketport} HTTP/1.0\r\nUser-Agent: fhem\r\n$pw\r\n";                               
+      syswrite $h->{conn}, $hdr;
+      my $buf;
+      my $len = sysread($h->{conn},$buf,65536);
+      if(!defined($len) || $len <= 0 || $buf !~ m/HTTP.*200/) {
+        HttpUtils_Close($h);
+        Log3 $name, 2, "$name: failed to open websocket via proxy";
+        return;
+      }
+
+      $hash->{CD} = $h->{conn};
+      $hash->{PORT} = $hash->{websocketport};
+      my $ret = "GET ws://$host:$hash->{websocketport} HTTP/1.1\r\n";
+      $ret .= HUEBridge_hash2header( {                  'Host' => "$host:$hash->{websocketport}",
+                                                     'Upgrade' => 'websocket',
+                                                  'Connection' => 'Upgrade',
+                                                      'Pragma' => 'no-cache',
+                                               'Cache-Control' => 'no-cache',
+                                           'Sec-WebSocket-Key' => 'RkhFTQ==',
+                                       'Sec-WebSocket-Version' => '13',
+                                     } );
+      $ret .= "\r\n";
+      syswrite($hash->{CD}, $ret );
+    };
+    HttpUtils_Connect($h);
+    return;
+  }
+
   if( my $socket = IO::Socket::INET->new(PeerAddr=>"$host:$hash->{websocketport}", Timeout=>2, Blocking=>1, ReuseAddr=>1) ) {
     $hash->{CD}    = $socket;
     $hash->{FD}    = $socket->fileno();

 

decade-submarginal