Create a seperate HTTPS site on lighttpd? - https

I'm running lighttpd on a Raspbian Pi3 Model B that serves as the HTTP webserver for Pi-Hole, a DNS based adblocker, running on port 80.
I'd like to also have lighttpd listen on port 443 for HTTPS requests, but have it direct to a completely different HTML file instead of Pi-Hole.
How can I do this (using a self-signed SSL certificate)?

This can be done with mod_proxy.
Add mod_proxy too your list of included modules in lighttpd.conf i.e:
server.modules = (
"mod_proxy"
)
Then you can redirect requires to 443 (https) somewhere else.
$SERVER["socket"] == ":443" {
proxy.server = (
"" => ((
"host" => "127.0.0.1",
"port" => "8080"
))
)
}

Related

Fetch emails through IMAP with proxy of form user:password:host:port

I have code to login to my email account to fetch recent emails:
def fetchRecentEmail(emailAddr, emailPassword, timeout=120):
host = fetch_imap_server(emailAddr) # e.g. 'outlook.office365.com'
with IMAP4_SSL(host) as session:
status, _ = session.login(emailAddr, emailPassword)
if status == 'OK':
# fetch most recent message
status, messageData = session.select("Inbox")
:
I'm trying to tweak it to go through a proxy.
ref: How can I fetch emails via POP or IMAP through a proxy?
ref: https://gist.github.com/sstevan/efccf3d5d3e73039c21aa848353ff52f
In each of the above resources, the proxy is of clean form IP:PORT.
However my proxy is of the form USER:PASS:HOST:PORT.
The proxy works:
USER = 'Pp7fwti5n-res-any-sid-' + random8Digits()
PASS = 'abEDxts7v'
HOST = 'gw.proxy.rainproxy.io'
PORT = 5959
proxy = f'{USER}:{PASS}#{HOST}:{PORT}'
proxies = {
'http': 'http://' + proxy,
'https': 'http://' + proxy
}
response = requests.get(
'https://ip.nf/me.json',
proxies=proxies, timeout=15
)
The following code looks like it should work, but errors:
HOST = 'outlook.office365.com'
IMAP_PORT = 963
PROXY_TYPE = 'http' # rainproxies are HTTP
mailbox = SocksIMAP4SSL(
host=HOST,
port=IMAP_PORT,
proxy_type=PROXY_TYPE,
proxy_addr=URL,
proxy_port=PORT,
username=USER,
password=PASS
)
emailAddress, emailPassword = EMAIL.split(',')
mailbox.login(emailAddress, emailPassword)
typ, data = mailbox.list()
print(typ)
print(data)
I needed to add a timeout arg/param in 2 places to get the code to run:
def _create_socket(self, timeout=None):
sock = SocksIMAP4._create_socket(self, timeout)
server_hostname = self.host if ssl.HAS_SNI else None
return self.ssl_context.wrap_socket(
sock, server_hostname=server_hostname
)
def open(self, host='', port=IMAP4_PORT, timeout=None):
SocksIMAP4.open(self, host, port, timeout)
Rather confusing that nobody else seems to have flagged that in the gist.
But it still won't work.
If I use any number other than 443 for IMAP_PORT I get this error:
GeneralProxyError: Socket error: 403: Forbidden
[*] Note: The HTTP proxy server may not be supported by PySocks (must be a CONNECT tunnel proxy)
And if I use 443, while I now get no error, mailbox = SocksIMAP4SSL( never completes.
So I am still far from a working solution.
I am hoping to run this code simultaneously on 2 CPU cores, so I don't understand the implications of using port 443. Is that going to mean that no other process on my system can use that port? And if this code is using this port simultaneously in two processes, does this mean that there will be a conflict?
Maybe you can try monkeypatching socket.socket with PySocket.
import socket
import socks
socks.set_default_proxy(socks.SOCKS5, HOST, PORT, True, USER, PASS)
socket.socket = socks.socksocket
Then check if your IMAP traffic is going through a given proxy.

Ruby Tor Switching Ip - "general SOCKS server failure" unless I spawn a new process to telnet into Tor control port

When trying to switch Tor IP address using telnet, I am running into SOCKSError::ServerFailure: general SOCKS server failure when trying to connect to the Tor control port via telnet. However if I spawn a new process to do the telnetting, I have no problem. I dont want to spawn a new process because its ugly. I was hoping someone could help me find why I have this problem and a more rubust solution?
To reproduce:
start tor:
tor --SocksPort 9350 --ControlPort 53500 --CookieAuthentication 0 --HashedControlPassword <passwordhash> --DataDirectory /tmp/tor_data/9350
Then run this ruby code which uses socksify to setup a socks server, then uses the tor gem Tor::Controller.connect block which connects to the Tor control port via telnet to switch Tor endpoint:
require 'socksify'
require 'terminator'
require 'tor'
TCPSocket::socks_server = "127.0.0.1"
TCPSocket::socks_port = "9350"
Tor::Controller.connect(:port => 53500) do |tor| #<- error
tor.authenticate("")
tor.signal("newnym")
end
Error at Tor::Controller.connect call:
SOCKSError::ServerFailure: general SOCKS server failure
If I replace the Tor::Controller.connect block with this (spawning a new process to do the telnetting), I have success:
telnet_pid = nil
begin
Terminator.terminate :seconds => 20 do
cmd = "bundle exec ruby -e \"require 'tor'\" -e " +
"\"Tor::Controller.connect(:port => 53500)" +
"{|tor| tor.authenticate(''); tor.signal('newnym')}\""
telnet_pid = Process.spawn(cmd)
Process.wait telnet_pid
end
rescue Terminator.error
puts 'Telnet process to switch Tor endpoint timed out!'
Process.kill('TERM', telnet_pid) if telnet_pid
end
I realised that the socks server was routing all TCP requests through the SOCKS server including my telnet requests. If I disable the socks server while telnetting then re-enable it again it works:
TCPSocket::socks_server = nil
TCPSocket::socks_port = nil
Tor::Controller.connect(:port => 53500) do |tor| #<- error
tor.authenticate("")
tor.signal("newnym")
end
TCPSocket::socks_server = "127.0.0.1"
TCPSocket::socks_port = "9350"

Padrino websockets + Heroku; Connection closed before receiving a handshake response

I am using padrino websockets (https://github.com/dariocravero/padrino-websockets) to provide a chat system for my site, and it works great on my local machine. However, after deploying to heroku (free), the websocket won't make a connection and will return
failed: Connection closed before receiving a handshake response
It works fine on localhost, where I am using this to connect:
connection = new WebSocket('ws://localhost:3000/channel');
But, when used on heroku with this:
connection = new WebSocket('ws://******.herokuapp.com:3000/channel');
it returns a handshake error (above)
My implementation server side
websocket :channel do
on :newmessage do |message|
currentAccount = Account.find_by(lastLoginIP: message["ip"]) rescue nil
if currentAccount != nil
broadcast :channel, {
"name" => currentAccount.nickname,
"url" => currentAccount.url,
"image" => currentAccount.image,
"chatmessage" => message["chatmessage"][0..80]
}
end
end
end
inside my main Padrino app.rb, and this in my Procfile. What is going on?
web: bundle exec puma -t 1:16 -p ${PORT:-3000} -e ${RACK_ENV:-production}
Your Websocket port (3000) isn't publicly available on Heroku.
Heroku forwards any requests made to port 80 or port 443 to the dynamic port of your web dyno, stored in the $PORT bash variable.
In your browser (client), try replacing this line:
connection = new WebSocket('ws://localhost:3000/channel');
With this line:
connection = new WebSocket('ws://' + window.document.location.host + 'channel');
Or, if you want to support both SSL and unencrypted Websockets:
ws_uri = (window.location.protocol.match(/https/) ? 'wss' : 'ws') +
'://' + window.document.location.host + 'channel';
connection = new WebSocket(ws_uri)
It should work if both your app and the websocket layer are sharing the same server.

lighttpd configuration to proxy/rewrite from one domain to another

i need to setup proxy/rewrite on lighttpd!
i have server1, which serves via http 2 different web app paths:
* http://server1/path1
* http://server1/path2
also, i have lighttpd server in front of server1
i want to setup rewriting and/or proxing on lighttpd, so that each of the 2 paths would be served as root path on different domains:
* requests to http://server2.com/* are proxied/rewrited to http://server1/path1/*
* requests to http://server3.com/* are proxied/rewrited to http://server1/path2/*
important:
server2.com and server3.com can access server1 only via http
redirects are not the option, users of server2.com & server3.com shouldn't not know that the actual web apps are served from different paths of server1.
Is it possible?
Your need is known by lighttpd developers from several years.
It is answered by a workaround or new feature depending on the version.
Lighttpd 1.4
A workaround is explained in the bugtracker : bug #164
$HTTP["url"] =~ "(^/path1/)" {
proxy.server = ( "" => ("" => ( "host" => "127.0.0.1", "port" => 81 )))
}
$SERVER["socket"] == ":81" {
url.rewrite-once = ( "^/path1/(.*)$" => "/$1" )
proxy.server = ( "" => ( "" => ( "host" => "server2.com", "port" => 80 )))
}
Lighttpd 1.5
They added this feature with this command (official documentation) :
proxy-core.rewrite-request : rewrite request headers or request uri.
$HTTP["url"] =~ "^/path1" {
proxy-co...
proxy-core.rewrite-request = (
"_uri" => ( "^/path1/?(.*)" => "/$1" ),
"Host" => ( ".*" => "server2.com" ),
)
}
Update: lighttpd 1.4.46 (released in 2017) introduced proxy.header which can perform limited URL-prefix rewriting. More info at lighttpd mod_proxy

perl Socket6 binding to only one wildcard address

I have following program in perl which is supposed to listen on IPv6 address, and by theory should serve to both IPv4 (through IPv4 mapped IPv6 address) and IPv6 clients on a dual stack box.
use Socket;
use Socket6;
#res = getaddrinfo('', 8086, AF_UNSPEC, SOCK_STREAM,0, AI_PASSIVE);
my #ipv6Result;
while(scalar(#res)>=5){
my #currentResult = #res;
($family, $socktype, $proto, $saddr, $canonname, #res) = #res;
if($family == AF_INET6){
#ipv6Result = #currentResult;
}
}
if(#ipv6Result){
($family, $socktype, $proto, $saddr, $canonname) = #ipv6Result;
}
socket(Socket_Handle, $family, $socktype,$proto) || next;
bind(Socket_Handle,$saddr ) || die "bind: $!";
listen(Socket_Handle, 1) || die "listen: $!";
$paddr = accept(Client,Socket_Handle) || die "accept: $!";
After running this the netstat gave following observation:
c:\Perl\bin>netstat -nao | findstr 8086
TCP [::]:8086 [::]:0 LISTENING 2892
It seems, it is listening on only IPv6 wildcard address (::) and not on IPv4 wildcard address (0.0.0.0). I was not able to connect this server process from an IPv4 client, but was able to connect through an IPv6 client.
I tried a similar server program in java as follows (on the same setup):
import java.net.ServerSocket;
public class CodeTCPServer {
public static void main(String[] args) throws Exception{
new ServerSocket(8086).accept();
}
}
The netstat output for this was as follows:
C:\Users\Administrator>netstat -nao | findstr 8086
TCP 0.0.0.0:8086 0.0.0.0:0 LISTENING 3820
TCP [::]:8086 [::]:0 LISTENING 3820
Seems to listen on both IPv6 and IPv4, and I am also able to connect it from IPv4 and IPv6 clients.
If I run the same perl program on a linux box it works fine, and I am able to connect to it through IPv4 and IPv6 clients.
I wonder, if something on windows is stopping the perl program from listening on both IPv4 and IPv6 (but then it should have stopped the java program as well for the same reason). If some problem with the program logic it shouldn't have worked on linux as well.
(I am using Socket6 for now, as I couldn't use perl's inbuilt support for IPv6 somehow on windows, I am in communication with the authors to get it worked on my setup)
UPDATE:
I just tried following:
setsockopt (Socket_Handle, IPPROTO_IPV6, IPV6_V6ONLY, 0 ) or print("\nFailed to set IPV6_V6ONLY $! ");
in anticipation that the socket option has default value 1 (for this platform), and I have to manually override it, but alas! I got following error:
Your vendor has not defined Socket macro IPV6_V6ONLY, used at c:\socket6\Socket6Server.pl line 66
Now I wonder what does 'vendor' mean, is it Socket6 module / perl vendor or OS vendor ?
UPDATE2
I think the answer is given in http://metacpan.org/pod/IO::Socket::IP (for the V6Only argument)
with following lines:
If your platform does not support disabling this option but you still want to listen for both AF_INET and AF_INET6 connections you will have to create two listening sockets, one bound to each protocol.
And this worked for me! But then I need to check if the platform supports V6Only disabling
(protocol aware code in my program :( ), when compared to Java, Java does it automatically for me (checking and creating 2 sockets).
This requires the BIND_V6ONLY socket option to be turned off. See the IO::Socket::IP source for details on how.
Also, in response to your comment
I am using Socket6 for now, as I couldn't use perl's inbuilt support for IPv6 somehow on windows, I am in communication with the authors to get it worked on my setup)
That's not strictly true, if memory serves. You were having trouble with IO::Socket::IP but the plain Socket stuff should all be working fine. You don't need to be using Socket6 because Socket 2.006 already has everything that does. You can replace your code with:
use Socket qw( :addrinfo SOCK_STREAM AF_INET6 );
my ($err, #res) = getaddrinfo('', 8086,
{ socktype => SOCK_STREAM, flags => AI_PASSIVE });
my $ipv6Result;
my $current;
while(#res){
$current = shift #res;
if($current->{family} == AF_INET6) {
$ipv6Result = $current;
}
}
if($ipv6Result) {
$current = $ipv6Result;
}
socket(my $sock, $current->{family}, $current->{socktype}, $current->{proto}) or next;
bind(my $sock ,$current->{addr}) or die "bind: $!";
listen(my $sock, 1) or die "listen: $!";
my $paddr = accept(my $client, $sock) or die "accept: $!";

Resources