This manual is complete but should still be considered a work in progress. Dated August 30, 2024.
Some details are not covered here. Please refer to the utilities and usage examples in the installation walkthrough
The
However, the following minimum versions are required for some features:
HTTPS restart command | |
RSA sign/verify (certificate creation) | |
TLS handshake mimicry |
Part 1 | File access permissions - the Kraker security model |
Part 2 | Detailed structure of a proxy request |
Part 3 | Shadow port management |
Part 4 | Shadow port forking |
Part 5 | Advanced hacking: local file and directory access |
Part 6 | Advanced hacking: passing cookies with the Accept header; zz-location and zz-set-cookie |
Part 7 | Advanced hacking: shadow ports and rabbit holes |
Part 8 | Advanced hacking: the internal commands (timeout, vpx, key, mock) |
Part 9 | Performance notes |
Javascript is normally restricted by the web browser from freely accessing the file system but this limit can be bypassed via the proxy server but with some qualifications (else this ability would be fatally dangerous). These basic rules apply:
1) All files and directories in the Kraker home directory are accessible for reading.
2) A new file can be opened for writing but it is not permitted to modify an existing file.
3) No access at all is possible outside of the Kraker home directory.
A special file called
Example entry in the aliases file:
You may include whatever comments or whitespace as you like. The proxy server looks for a given name in between a plus sign and a comma. If the name is found, then the proxy will look for a path string in between a plus sign and a semicolon. A directory path is indicated by a terminating slash (in front of the semicolon). To enable a file or directory for writing, put a question mark at the end of the alias (in front of the comma). The alias may not contain a colon, slash, backslash, question mark or asterisk. It should not contain a comma, semicolon, whitespace or a plus sign (other than the first one).
File reading is implemented via the GET method in a standard HTTP request. An alias must be prepended with the plus sign. Files may be created, overwritten or appended via the PUT method. The HEAD method is also available for retrieving the file size or simply to check whether a file or directory exists. No other mechanism has been provided for accessing the file system. Examples of a fetch request in Javascript:
The first two examples can be simulated by just entering the URL in the web browser. The GET method will return a list of files (but not directories) if a file path resolves to a directory. Two notes on the Kraker home directory: 1) the files are not listable and 2) directories contained within are accessible and the files are listable. Directory names and aliases should be treated as you would treat a password. This is your only protection against malicious scripts.
Refer to the section
Important request headers:
Important response headers:
The header
Multiple request/response headers or internal commands must be separated by a vertical bar ( | ) and the final header must
end with a vertical bar and an asterisk ( |* ). The URL of the destination follows. If a header value needs to be URI
decoded (due to the presence of special characters such as spaces) then prepend the value with an exclamation mark. You
may use a tilde in place of the vertical bar. If you are using a Chrome-based browser, you will notice that the vertical
bar is replaced with
The destination can be a file path in the Kraker home directory or an alias in the form
A special note about case: do not use uppercase characters in header names else unexpected behaviour may occur. The header "Accept" is not the same as "accept". This is due to a limitation in the way headers are handled in Node.js which, in turn, is a limitation in the way Javascript handles object attribute names (the names are case-sensitive). The HTTP standards require that case be ignored when processing header names. The web browser employs mixed-case (also known as camel-case) in header names as a stylistic convention and not because it is required.
The best way to familiarize yourself with the URL syntax is to watch the proxy console while playing some videos in Alleycat Player. You will see each request as it is sent to the destination server as the app fetches one or more files in its search for a video link.
You may notice that Alleycat Player sometimes inserts a double-comma in the Origin/Referer field. This is a special syntax for m3u8 files which resolves a problem with relative URLs. This type of URL lacks the domain name which is the name of the server from where the file was retrieved. This is an issue when passing the video through Kraker because the HLS/m3u8 playback module will submit an incorrect URL to the proxy server. In order to fix this, Kraker must load the m3u8 and correct the affected links.
@ extension for assigning the IP address/port or redirecting to a localhost server:
Use IP address | |
Use IP address of | |
Use port 1080 | |
Use IP address | |
Redirect to "localhost:8000" with server + path + query | |
Redirect to "localhost:8000" with server + "@test" + path + query |
The first four examples are self-explanatory. If the IP address is IPv6 then the address must have a trailing colon if the port number is absent (square brackets are allowed but the trailing colon rule still applies). In the last two examples, Kraker connects to the other localhost server with HTTP only. The URL passed is the same as what was originally passed to Kraker (either directly or through a shadow port). The URL includes "@test" appended to the domain name in the last example (can be used only if the other server is known to understand it).
Refer to the section
The domain editor syntax is as follows (using "shadow" as an alias for "localhost:8080"):
You can create shadow ports in your Kraker settings file. For example:
To play a music file, you could just type
Alternatively:
Use "SHD" by itself to delete a shadow port. Use named groups with the "activate" command:
Multiple domains may be specified (separated by vertical bar). The prefixes ($~) may be applied separately:
Note that whitespace (including newline) is permitted around the vertical bar.
The string "$$$" may be used in place of the server name:
Resolvers may be created or removed using the domain editor. Append a plus sign to the domain name:
The values TOR, VPN, LOCAL and FETCH are not recognized. Special cases:
Forking serves three purposes:
The first example was mentioned in the previous section. This may be used to access local files or a website. It can be
used in any application (not just in a web browser) because the Socks5 proxy is not required. The origin must be dotless
(like "localhost" or "shadow") and the domain name in between the dollar signs must also be dotless. This policy exists
to prevent an app from using the forking feature to detect website mimicry.
The second example may be used to force a web page to load locally instead of through a website (you will need to also
create the shadow port). Replace "pathname" with the original file path on the target server. The "window.location" should
look normal to the Javascript inside the page (such as a bot challenge) since the "$secret$test.html" part is in
a query string.
The third example is the same as the second except that a local file name is not present. This command will return the
cookie string sent to the server by the web browser. It is possible that a particular cookie may only apply on a
particular server path but that functionality is rarely used. You generally just want to get the cookies at the server
root.
There is an additional method of forking a dotless shadow port without the Socks5 proxy but it seems to only work from
a web browser. The trick lies in how a "localhost" subdomain resolves to an IP address. It seems that most (all?)
web browsers ignore the subdomain part. For example:
This request appears at "localhost:8080" with the host name "mymusic.localhost" which the server can then resolve
to a shadow port. If I try this from an external app like my favourite video player (SMPlayer) then the request will
fail with a DNS error. SMPlayer tries to resolve through the system DNS which does not work. Just something that I thought
was fun to implement but I'm disappointed that the trick only works in a browser.
The procedure employed by Kraker is as follows (after stripping the preamble from the URL):
1)
Step 4 - A file name containing the "@" symbol can be freely rewritten. If a directory name contains
the symbol then all files within are rewriteable. Placement of the symbol at the beginning of the name is recommended
so that it can be readily identified.
Step 5 - The URL is split at the first slash to get the alias. If the alias resolves to a directory (terminating
slash) then the additional path information is added else it is discarded. The file path found in the aliases file is not
checked for correctness (it is the user's responsibility so anything goes).
Step 6 - If the method is GET and the file exists then the file will be streamed back to the client. If the method
is PUT and the file does not already exist then the file may be written else it cannot unless an alias with write permission
has been specified or the URL contains the "@" symbol. There are four possible write operations:
overwrite, append, write-in-place and write-in-place plus truncate. It is not possible to delete a file (because removing a
file without leaving a trace is considered a security risk). Whereas previous versions of Kraker permitted writing to
the home directory, this is no longer allowed (a malicious app could just write junk to fill up the local drive). Writing
is only permitted to a directory within the home directory.
If the URL resolves to a directory, the PUT method is disallowed while the GET method returns the list of file names
(excluding any sub-directories). It is not possible to list the file names in the home directory. The inability to list
directory names is important for security so that malicious apps cannot compromise the file system without foreknowledge.
Of course, it is possible to cycle through a list of potential names in order to find a crack in your security which is
why you should try to pick unobvious directory names and keep them secret.
The GET method supports the Range header so that a file may be read from an arbitrary position (to open a video, for
example). Specifications are not given here since this is covered by the HTTP standards (Kraker is compliant except that
it does not recognize multiple range specifiers). Files are streamed using the Node.js stream handlers so size is not
a factor. The append mode is invoked with a plus sign at the end of the URL or, in the case of an alias, at the beginning.
For example,
Write-in-place means overwriting a specific part of a file rather than all of it. This involves using the Range header
(similar to the GET method). Note that there is no explicit HTTP specification that covers this. A method called PATCH
has been proposed but, in reality, each platform approaches this in its own manner (if it supports this mode at all) due
to the security and integrity issues involved.
Write-in-place is implemented by specifying a range in the form "0-500" where the first parameter is the start position
in the file and the second parameter is the end position. If the start position is greater than the file size then the
request is rejected (this means that it is permitted to append to the file or to overwrite the end of the file). The request
body is loaded into memory and there is an arbitrary size limit of 500,000 bytes. Once the payload has been received, the
size is compared to the expected size given by the range specifier. If it is not the same then the request is rejected.
Exercise caution when writing strings containing Unicode because the string length is not the same as the size of the
payload in bytes.
Compute payload size in bytes:
The truncate mode, like the append mode, is invoked with the plus sign. In this case, the end position must be one greater.
That is, the end position is the truncation point, not the position of the final byte. This slight difference allows a file
to be truncated without writing anything. To clarify, the range "10-10" would write one byte in normal mode while the same
range in truncate mode would simply truncate the file.
The HEAD method returns the following headers:
This is functionality which can only be invoked from a Javascript program. Cookie strings can be rather long so, instead
of passing the cookies as a parameter in the URL string, the Accept header may be used. Here's a sample fetch statement:
The cookie string must be prepended with a double asterisk. The proxy server will change the Accept header value to
Two secondary functions may be invoked by setting the Accept header. The fetch statement does not provide a way to
control or block redirection so the proxy server will delete the
This functionality is not available to shadow ports. The additional headers are exposed via
A basic shadow port is easy to set up but, for real hacking, a number of features exist that will help to simplify your
task should you seriously want to get into the nitty-gritty. This is a basic shadow port:
The triple dollar sign is a placeholder for the domain name (to save you a lot of extra typing). The "null" part keeps the
Origin and Referer headers as they are sent by the web browser. The tilde tells the proxy to suppress console output and
return all response headers to the browser. This makes the shadow port completely transparent. Of course, the web browser
knows that the certificate is fake but that information is not available to lower processes nor can a script detect any
difference in the response headers. As far as the destination server is concerned, there is nothing unusual going on but
there is one caveat and this is covered in the next section (the
This will make Kraker look like a Firefox browser rather than a Node server. It doesn't always work but it works well
enough. Worst case scenario is that you may have to give up on hacking the site but you should be able to get by with
solving the Cloudflare challenge. The challenge will result in an access cookie which you may or may not need to extract,
depending on what you want to accomplish. The process of cookie extraction was covered earlier. Note that the cookie
extraction can be done with a fake sub-domain. For example,
A shadow path (in conjunction with a shadow port) is mainly used to replace a remote file with a local copy or simply to
redirect to a dead end. When hacking a site, it may be necessary to download a file from the server and make changes to it
in order to discover what it does. A shadow path is created nearly the same as a shadow port. The difference is the
presence of a slash after the domain name:
A port number is not associated so it works for both HTTP and HTTPS. The slash at the beginning of the parameter string
indicates that this replaces the original path rather than the original path being added at the end (as you would normally
want done with a shadow port). The example will replace the site icon with an icon loaded from a local file. You could, of
course, load the icon from another server as well. Whatever you can do with a shadow port works for a shadow path. In
case you need to fool around with the query string:
Browser request:
In the above example, you are sending the request to the server with additional query parameters. If you use a double
question mark or just a single question mark with nothing after it, then the original query string is deleted. You can send
a double query string with "&&":
A shadow port must be created for any the above to work. We're not done exploring the rabbit hole yet:
The second example is more complex. It sends the connection to an IP address owned by Google. The dollar sign in front of
the address instructs the Socks5 proxy to insert a TLS bridge to mask the invalid certificate at the other end (the
browser will otherwise reject the connection). The bridge is an upgraded socket using a forged certificate. What you end
up with is Google instead of Bitchute, though the browser can't discern the difference. Ultimately, this doesn't work well
but it's just an exercise. Note that the TLS bridge is not activated if the second dollar sign is not present. This is also
applicable to the first example in a case where the other localhost server cannot supply a valid certificate.
If at all possible, it is best policy to never divulge the shadow secret. In the case of cookie extraction, it is possible
to avoid revealing the shadow secret by preparing the shadow port outside of the app which needs it:
The second example is what the app would use to extract the cookie without needing the shadow secret. The colon is not
strictly necessary since the string "abc123" does not evaluate to a valid port number though it might be good practice to
include it (you could also just leave blank). To be totally clear, the Socks5 proxy redirects to the HTTPS proxy in this
instance. Here's a sequence which employs a path inserter and an icon inserter:
The "(/stuff)" part in the second line is replaced with the shadow path defined in the first line and then the
"(~favicon.ico)" part is either discarded or kept depending on whether the original path is equal to "favicon.ico". Note
that this is the only way to have both a path inserter and an icon inserter. That is, the shadow port cannot have both but
it works here because the payload is split. It gets more interesting when we pile on this weird feature:
Some DNS providers offer a "family-friendly" version of their DNS which filters out adult websites and potentially
malicious actors. This works (though not really) by returning the DNS provider's own IP address for the undesirable site.
If the browser sent the request as HTTP, a warning page can pop up. Unfortunately, HTTPS is a dead end due to the
certificate mismatch. By installing the above in your settings file, you can deliver your own custom result without the
certificate issue. The example contains the IP address returned by Adguard's family DNS. I'm not sure that this feature
has much use but you can sure shock someone if you pick the right image (evil laugh).
The HTTP/HTTPS proxy employs a 30-second timeout for a connecting socket and a 3-minute timeout for an idle socket
(there are no timeouts in the Socks5 proxy). The first timeout is employed to guard against an unreliable third-party
proxy server which may connect but fail to respond promptly afterward (your computer's operating system allows
21 seconds for a server to connect). The idle timeout will terminate a connection if no traffic has been detected for
the time period. The default time is generally long enough to not interfere with normal operation though it is not
unusual for a browser or other application to attempt to keep an idle socket open for a longer period.
The timeout internal command (format:
Similar to the "VPN" option provided by the Socks5 proxy, the HTTP/HTTPS proxy supports the use of a third-party proxy
at the level of an individual connection. This allows an application to use any number of proxies for web scraping or
whatever purpose. By default, Kraker does not validate the security certificate for HTTPS connections. Use a
terminating colon or plus sign to enable validation (
The default behaviour is to delegate DNS lookups to the third-party proxy server. This is considered more secure since
it prevents a potential attacker from deducing your location from your DNS access pattern. You can force local DNS in
your settings file:
Use "!" in both the username and password fields for an HTTP proxy. To enable the TLS bridge, use "$" in the password
field. Authentication is not supported for HTTP proxies. For a Socks5 proxy, use "$" in front of both the username and
password to enable the TLS bridge. For a localhost HTTP proxy, you can use the IP address "0.0.0.0" or "0.0.0.1" (for the
TLS bridge) instead of configuring the username and password. Finally, it is possible to employ dual Socks5 proxies by
simply adding the second proxy address to the first one:
Note that the
Policies have been implemented for the proper handling of cookies on shadow ports and for securing the cookies
from abuse by potential attackers. Kraker will observe the state of the Origin request header and adjust the response
headers
An application that wishes to include credentials on the shadow port must transmit the access key (as shown in the second
line above). The access key (with a dollar sign at each end) may appear anywhere in the path string or the query string. It
will be completely removed before transmission to the destination. If the key is an empty string then nothing is
added to the path but the shadow port will be open to abuse. Note that some sites disallow third-party cookies and the
browser may also have its own restrictions. For these reasons, it is often not possible to use third-party cookies. The
only solution is to run your script under the same domain or a sub-domain.
Regarding Cloudflare, a feature has been added for the purpose of mimicking the behaviour of a
web browser. This is needed to bypass the Cloudflare Bot Fight Mode (BFM). There is no way for Kraker to perfectly mimic
a browser but 80% similar is usually enough unless the website owner has the BFM configured to a higher security level.
There are two issues: compliance with the camel-case format of certain headers and the TLS handshake fingerprint. The
"mock" command meets these requirements:
The first parameter may be 1, 2, 3 or none. This refers to the camel-case of request header names. For example,
"User-Agent" instead of "user-agent". Either is acceptable under the HTTP standards but Cloudflare looks for the camel-case
in specific header names in order to weed out suspicious clients (including the Node.js platform used by Kraker). These
headers are critical:
Kraker normally transmits request headers with the names in all lower-case (this is typical behaviour for non-browser
platforms). The headers listed above may be corrected with option "1" (regardless of the original case). Option "2"
transmits the header names as presented by the browser. Option "3" does both. Only the first option is needed for
Cloudflare and, in some cases, it might be enough.
The TLS handshake fingerprinting issue is harder to fix. At present, Kraker can customize certain TLS options to mostly
mimic a Firefox browser. This is the "A" option. It is possible that other options may become available in the future. Note
that this customization is not possible with versions of Node.js earlier than 12.11.0 and might be questionable with newer
versions but, at the time of this writing, it seems to work fine under Node 18. Of course, Cloudflare could change its
policies at any time.
Use the "X" option to connect with HTTP/2 (this is more or less experimental though it seems to work fine). This can be used
along with the "A" option but the camel-case options are irrelevant because header names are exclusively lower-case.
The HTTP/HTTPS proxy employs a socket reuse policy to avoid the time cost of opening a new connection for every
transaction. This behaviour is not linked to the status of the incoming connection. An idle socket will be kept open
for 30 seconds (not configurable). A longer timeout would run the risk that the server might close the connection
prematurely. It is possible that a server might time out in less than 30 seconds but I have not seen such a case. The
TLS session can also be reused for another socket to the same server (there is no reuse after the sockets are closed).
Additionally, the Socks5 proxy (which is used by the HTTP/HTTPS proxy) employs a connection retry policy which can
sometimes help with a stubborn server. The policy is to retry the connection in 3 seconds if contact with the server
fails within 12 seconds. That is, the server connects but then disconnects. This can happen if the server is refusing
connections because it is too busy. Or the server could just be flaky. My observations indicate that the retry policy
can rescue a failed connection attempt about 10% of the time.
A crash report is printed on the console when the server crashes but this won't be visible if the console closes
(default behaviour under Windows and maybe Linux). See the file
Kraker supports IPv6 but I am not able to test this functionality since my router and/or my ISP does not support it.
Also, the DNS manager is not configured to do IPv6 lookups because IPv6 is still not widespread (less than 30% adoption
depending on region and other factors). If you need to access an IPv6-only site, you can do so by routing through the Tor
server or by hardwiring the address in your settings file.
http://shadow/@secret@www.anysite.com+@127.0.0.1:9050+
http://shadow/@secret@www.anysite.com+@+1.2.3.4+127.0.0.1+9050
http://shadow/@secret@www.anysite.com+@
2)
3)
4)
5)
6)
http://shadow/@secret@www.anysite.com@$~*null*!mock:1A|*https://$$$
http://shadow/@secret@www.anysite.com/favicon.ico@/~favicon.ico
http://shadow/@secret@www.anysite.com/something.html@~https://$$$?x=1&y=2
Modified request:
Result:
The main purpose of the redirector is to pass the connection to another server. In the simplest case, all you need is
something like "@8000@" (no colon required) to redirect all connections to "localhost:8000". For example:
http://localhost:8080/@secret@www.bitchute.com@@$142.251.33.164:443@$
https://www.bitchute.com/?@abc123:@
http://localhost:8080/@secret@www.bitchute.com@$(/stuff)https://$$$
Result:
https://www.bitchute.com/pathname$abc123$