Skip to content

Commit 7ba46c4

Browse files
committed
DOCSP-33426: socks5 proxy server (#146)
* DOCSP-33426: socks5 proxy server * first pass fixes * JS PR fixes (cherry picked from commit f9ec693)
1 parent 969d2bc commit 7ba46c4

File tree

6 files changed

+257
-0
lines changed

6 files changed

+257
-0
lines changed

examples/src/test/kotlin/SocksTest.kt

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import com.mongodb.ConnectionString
2+
import com.mongodb.MongoClientSettings
3+
import com.mongodb.MongoException
4+
import com.mongodb.kotlin.client.coroutine.MongoClient
5+
import config.getConfig
6+
import kotlinx.coroutines.runBlocking
7+
import org.bson.BsonInt64
8+
import org.bson.Document
9+
import org.junit.jupiter.api.AfterAll
10+
import org.junit.jupiter.api.Assertions
11+
import org.junit.jupiter.api.TestInstance
12+
import kotlin.test.Ignore
13+
14+
// :replace-start: {
15+
// "terms": {
16+
// "CONNECTION_URI_PLACEHOLDER": "\"<connection string>\"",
17+
// "${uri}&": "mongodb+srv://<user>:<password>@<cluster-url>/?"
18+
// }
19+
// }
20+
21+
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
22+
internal class SocksTest {
23+
24+
/* NOTE: SOCKS5 tests are not run by default. To run these tests,
25+
* you need access to proxy server credentials.
26+
* Replace the placeholders in the test with your credentials, then replace
27+
* the @Ignore annotation with @Test on the tests you want to run.
28+
*/
29+
30+
companion object {
31+
private val config = getConfig()
32+
val CONNECTION_URI_PLACEHOLDER = config.connectionUri
33+
var higherScopedClient: MongoClient? = null
34+
35+
@AfterAll
36+
@JvmStatic
37+
fun afterAll() {
38+
runBlocking {
39+
higherScopedClient?.close()
40+
}
41+
}
42+
}
43+
44+
@Ignore
45+
fun mongoClientSettingsSocks() = runBlocking {
46+
// :snippet-start: socks-mongoclientsettings
47+
val uri = CONNECTION_URI_PLACEHOLDER
48+
49+
val mongoClient = MongoClient.create(
50+
MongoClientSettings.builder()
51+
.applyConnectionString(ConnectionString(uri))
52+
.applyToSocketSettings{ builder ->
53+
builder
54+
.applyToProxySettings{ proxyBuilder ->
55+
proxyBuilder
56+
.host("<proxyHost>")
57+
.port("<proxyPort>".toInt())
58+
.username("<proxyUsername>")
59+
.password("<proxyPassword>")
60+
.build()
61+
}
62+
}
63+
.build()
64+
)
65+
// :snippet-end:
66+
lateinit var higherScopedCommandResult: Document
67+
val database = mongoClient.getDatabase("admin")
68+
try {
69+
// Send a ping to confirm a successful connection
70+
val command = Document("ping", BsonInt64(1))
71+
val commandResult = database.runCommand(command)
72+
println("Pinged your deployment. You successfully connected to MongoDB!")
73+
higherScopedCommandResult = commandResult
74+
} catch (me: MongoException) {
75+
System.err.println(me)
76+
}
77+
higherScopedClient = mongoClient
78+
Assertions.assertEquals(1.0, higherScopedCommandResult["ok"].toString().toDouble())
79+
}
80+
81+
@Ignore
82+
fun connectionStringSocks() = runBlocking {
83+
val uri = CONNECTION_URI_PLACEHOLDER
84+
// :snippet-start: socks-connection-string
85+
val connectionString = ConnectionString(
86+
"${uri}&" +
87+
"proxyHost=<proxyHost>" +
88+
"&proxyPort=<proxyPort>" +
89+
"&proxyUsername=<proxyUsername>" +
90+
"&proxyPassword=<proxyPassword>"
91+
)
92+
93+
val mongoClient = MongoClient.create(connectionString)
94+
// :snippet-end:
95+
lateinit var higherScopedCommandResult: Document
96+
val database = mongoClient.getDatabase("admin")
97+
try {
98+
// Send a ping to confirm a successful connection
99+
val command = Document("ping", BsonInt64(1))
100+
val commandResult = database.runCommand(command)
101+
println("Pinged your deployment. You successfully connected to MongoDB!")
102+
higherScopedCommandResult = commandResult
103+
} catch (me: MongoException) {
104+
System.err.println(me)
105+
}
106+
higherScopedClient = mongoClient
107+
Assertions.assertEquals(1.0, higherScopedCommandResult["ok"].toString().toDouble())
108+
}
109+
}
110+
// :replace-end:
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
val connectionString = ConnectionString(
2+
"mongodb+srv://<user>:<password>@<cluster-url>/?" +
3+
"proxyHost=<proxyHost>" +
4+
"&proxyPort=<proxyPort>" +
5+
"&proxyUsername=<proxyUsername>" +
6+
"&proxyPassword=<proxyPassword>"
7+
)
8+
9+
val mongoClient = MongoClient.create(connectionString)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
val uri = "<connection string>"
2+
3+
val mongoClient = MongoClient.create(
4+
MongoClientSettings.builder()
5+
.applyConnectionString(ConnectionString(uri))
6+
.applyToSocketSettings{ builder ->
7+
builder
8+
.applyToProxySettings{ proxyBuilder ->
9+
proxyBuilder
10+
.host("<proxyHost>")
11+
.port("<proxyPort>".toInt())
12+
.username("<proxyUsername>")
13+
.password("<proxyPassword>")
14+
.build()
15+
}
16+
}
17+
.build()
18+
)

source/fundamentals/connection.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Connection Guide
1111
/fundamentals/connection/mongoclientsettings
1212
/fundamentals/connection/network-compression
1313
/fundamentals/connection/tls
14+
/fundamentals/connection/socks5
1415

1516
.. contents:: On this page
1617
:local:
@@ -30,6 +31,7 @@ sections:
3031
- :ref:`Specify Connection Behavior with the MongoClient Class <specify-mongoclient-settings>`
3132
- :ref:`Enable Network Compression <network-compression>`
3233
- :ref:`Enable TLS/SSL on a Connection <tls-ssl>`
34+
- :ref:`Connect to MongoDB by Using a SOCKS5 Proxy <kotlin-connect-socks>`
3335

3436
For information about authenticating with a MongoDB instance,
3537
see :ref:`<authentication-mechanisms>` and :ref:`<enterprise-authentication-mechanisms>`.

source/fundamentals/connection/mongoclientsettings.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ to modify the driver's behavior:
291291
* - ``applySettings()``
292292
- Uses the socket settings specified in a ``SocketSettings`` object.
293293

294+
* - ``applyToProxySettings()``
295+
- Applies the ``ProxySettings.Builder`` block and then sets the
296+
``proxySettings`` field.
297+
294298
* - ``connectTimeout()``
295299
- Sets the maximum time to connect to an available socket before throwing
296300
a timeout exception.
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
.. _kotlin-connect-socks:
2+
3+
==========================================
4+
Connect to MongoDB by Using a SOCKS5 Proxy
5+
==========================================
6+
7+
.. facet::
8+
:name: genre
9+
:values: reference
10+
11+
.. meta::
12+
:keywords: code example, security, connection string
13+
14+
.. contents:: On this page
15+
:local:
16+
:backlinks: none
17+
:depth: 2
18+
:class: singlecol
19+
20+
Overview
21+
--------
22+
23+
In this guide, you can learn how to use the {+driver-long+} to connect
24+
to MongoDB by using a **SOCKS5 proxy**. SOCKS5 is a standardized
25+
protocol for communicating with network services through a proxy server.
26+
27+
.. tip::
28+
29+
To learn more about the SOCKS5 protocol, see the Wikipedia entry on
30+
:wikipedia:`SOCKS <w/index.php?title=SOCKS&oldid=1160087146>`.
31+
32+
.. _kotlin-socks-proxy-settings:
33+
34+
SOCKS5 Proxy Settings
35+
---------------------
36+
37+
The proxy settings specify the SOCKS5 proxy server address and your
38+
authentication credentials. You can specify your settings in an instance of
39+
``MongoClientSettings`` or in your connection string.
40+
41+
The following table describes the SOCKS5 client options:
42+
43+
.. list-table::
44+
:header-rows: 1
45+
:widths: 15 20 65
46+
47+
* - Name
48+
- Accepted Values
49+
- Description
50+
51+
* - **proxyHost**
52+
- String
53+
- Specifies the SOCKS5 proxy IPv4 address, IPv6 address, or hostname.
54+
You must provide this value to connect to a SOCKS5 proxy.
55+
56+
* - **proxyPort**
57+
- Non-negative integer
58+
- Specifies the TCP port number of the SOCKS5 proxy server. If you
59+
set a value for ``proxyHost``, this option defaults to ``1080``,
60+
but you can specify a different port number.
61+
62+
* - **proxyUsername**
63+
- String
64+
- Specifies the username for authentication to the SOCKS5 proxy server.
65+
The driver ignores ``null`` and empty string values for this setting.
66+
The driver requires that you pass values for both ``proxyUsername``
67+
and ``proxyPassword`` or that you omit both values.
68+
69+
* - **proxyPassword**
70+
- String
71+
- Specifies the password for authentication to the SOCKS5 proxy server.
72+
The driver ignores ``null`` and empty string values for this setting.
73+
The driver requires that you pass values for both ``proxyUsername``
74+
and ``proxyPassword`` or that you omit both values.
75+
76+
77+
Examples
78+
--------
79+
80+
The following examples show how to instantiate a ``MongoClient`` that connects
81+
to MongoDB by using a SOCKS5 proxy. The proxy settings can be specified in a
82+
``MongoClientSettings`` instance or a connection string. These examples use
83+
the placeholder values described in the :ref:`kotlin-socks-proxy-settings` section.
84+
Replace the placeholders with your proxy specifications and credentials.
85+
86+
Specify Proxy Settings in the MongoClientSettings
87+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
88+
89+
The following code example shows how to specify SOCKS5 proxy settings by
90+
using the ``applyToSocketSettings()`` builder method when creating a
91+
``MongoClientSettings`` instance:
92+
93+
.. literalinclude:: /examples/generated/SocksTest.snippet.socks-mongoclientsettings.kt
94+
:language: kotlin
95+
96+
Specify Proxy Settings in the Connection String
97+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
98+
99+
The following code example shows how to specify SOCKS5 proxy settings in
100+
your connection string:
101+
102+
.. literalinclude:: /examples/generated/SocksTest.snippet.socks-connection-string.kt
103+
:language: kotlin
104+
105+
API Documentation
106+
~~~~~~~~~~~~~~~~~
107+
108+
To learn more about the methods and types discussed in this guide, see the
109+
following API documentation:
110+
111+
- `MongoClientSettings.Builder <{+api+}/apidocs/mongodb-driver-core/com/mongodb/MongoClientSettings.Builder.html>`__
112+
- `SocketSettings.Builder <{+api+}/apidocs/mongodb-driver-core/com/mongodb/connection/SocketSettings.Builder.html>`__
113+
- `MongoClient.create() <{+api+}/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClients.html#create(com.mongodb.MongoClientSettings)>`__
114+
- `ProxySettings.Builder <{+api+}/apidocs/mongodb-driver-core/com/mongodb/connection/ProxySettings.Builder.html>`__

0 commit comments

Comments
 (0)