00:00:00.149
Dávid Halász is a software engineer working for Red Hat. He originally started as a C programmer but fell in love with Ruby early on and has been coding in it since 2012. He has given talks in various places, including Vienna, Brno, and Albania. Despite traveling from cold weather, he has come to present today in the hot, humid climate of Melbourne. In this talk, he will be discussing hijacking some sockets and HTTP connections.
00:52:920
Hello everyone, my name is Dávid. You can find me on Twitter under my full name or on GitHub as caitlin. Today, I'll be explaining how to hijack, proxy, and smuggle sockets using Ruby. I hail from the Czech Republic where I live in a town called Brno, which is famous for beer and MotoGP.
01:20:640
As a software engineer at Red Hat, I focus exclusively on open source, contributing to the ManageIQ project, which is a management platform for hybrid infrastructures. One feature I'm working on involves in-browser remote consoles. This means if you have a pool of virtual machines, you can open a VM and have a pop-up window displaying its virtual screen. When you use a browser, the VM operates in a hypervisor providing the remote console service. However, browsers typically do not understand VNC; they only comprehend HTTP or WebSocket. Therefore, we need something in between to translate the protocols.
02:36:340
The system I’m describing translates and transmits data between two points: Point A and Point B. When A is ready to read, and B is ready to write, the transmission occurs. This implementation requires sockets that act as abstractions around the networking stack, enabling operations akin to normal file handling in UNIX systems.
03:09:900
To utilize these sockets in Ruby, you need to require the necessary libraries. I am also demonstrating how I am opening an HTTP connection to the RubyConf website. When sending a request, I'm getting redirected, but I want to highlight that I'm reading and writing data. When you write to a socket, the operating system takes the data from the buffer, forms packets, and dispatches them to the network card. Depending on the data amount, this process may take varying durations due to network usage.
04:02:140
Data reading functions similarly. If there’s no data in the buffer, the thread will block and wait until data becomes available. This is what we call blocking I/O. Conversely, with non-blocking I/O, operations proceed without waiting for the entire buffer, instead operating only with the data currently available.
05:02:320
In Ruby, operations like write and read are part of specific methods that will raise exceptions when conditions like empty or full buffers occur. For non-blocking transfers, you could set up a loop until data becomes available, but this is not ideal as it consumes CPU cycles unnecessarily. To properly manage this, we use a system call called select. It allows you to query the operating system about the readiness of sockets within a specified timeframe, which can be adjusted according to need.
06:24.600
However, using select comes with downsides, especially when dealing with multiple sockets simultaneously, such as having two buffers testing readiness. A situation could arise where one socket is ready for reading whereas the other may not be ready for writing, which can lead to inefficiencies and an endless loop if not handled carefully.
07:14:680
To mitigate these issues, you can use blocking I/O with threads or explore event-driven solutions that effectively simulate non-blocking I/O. In our current setup, I redesigned the process to utilize dynamic arrays for sockets in action. When a socket is ready for reading, it gets removed from the array preventing re-checking in subsequent iterations, thus eliminating unnecessary CPU usage.
09:17.150
Even though the select method isn’t the most efficient, especially when working with numerous sockets, I explored alternatives like epoll, which registers sockets and provides a way to check their readiness in a more efficient manner. I also discovered interesting features in KQueue for BSD systems, allowing for greater efficiency in socket management.
11:42.700
The topic also leads me to discuss WebSockets, which extend HTTP connections allowing for bi-directional communications. In Ruby, web servers function via Rack, utilizing lambdas or Proc objects to manage requests and responses efficiently.
12:59.600
With respect to socket hijacking in Rack, it involves requesting the server to release its control over the socket. By leveraging Rack's hijack methods, we gain direct control over the socket, allowing us to manage further interactions directly, as illustrated in my code example.
13:59.440
Next, I delved into the concept of smuggling TCP traffic through HTTP connections. Essentially, if you can upgrade a connection to another protocol, you can essentially hijack the socket to use it for your preferred protocol, such as VNC or SSH. This would facilitate efficient connectivity through firewalls that only permit HTTP.
14:31.330
I've developed a proof of concept using a browser plugin, allowing users to connect to a remote desktop via SSH or VNC seamlessly, employing the principles of HTTP hijacking to create direct access paths without the hassle of complex routing.
15:45.780
The architecture is indeed complex, utilizing inputs from multiple sources and technologies. The server is implemented in Rack with Ruby, using a web extension plugin in JavaScript for client interaction, and this forms the backbone of the system, allowing user requests to be channeled effectively.
17:22.310
Finally, I showcased a live demonstration using Docker to connect to a VNC server and an SSH server running in isolated containers. My setup included deploying a static website enabling me to direct requests to the appropriate servers based on user needs without exposing any direct ports.
18:30.120
In conclusion, this setup illustrates how we can extend and manipulate connections using Ruby, opening up new pathways for accessing remote systems effectively while navigating around network constraints. Thank you for your attention!