Skip to content

Commit f005e11

Browse files
authored
proxy configuration for dmsgip (skycoin#285)
* make dmsgip able to use socks5 proxy to connect to dmsg * minor cli optimization * allow connection to dmsg server via socks5 proxy * implement flag to proxy conne\ction to dmsg for dmsgweb & dmsgcurl
1 parent 56d92f2 commit f005e11

File tree

6 files changed

+137
-44
lines changed

6 files changed

+137
-44
lines changed

cmd/dmsgcurl/commands/dmsgcurl.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/skycoin/skywire/pkg/skywire-utilities/pkg/cmdutil"
2525
"github.com/skycoin/skywire/pkg/skywire-utilities/pkg/logging"
2626
"github.com/spf13/cobra"
27+
"golang.org/x/net/proxy"
2728

2829
"github.com/skycoin/dmsg/pkg/disc"
2930
"github.com/skycoin/dmsg/pkg/dmsg"
@@ -43,6 +44,9 @@ var (
4344
dmsgcurlWait int
4445
dmsgcurlOutput string
4546
replace bool
47+
proxyAddr string
48+
httpClient *http.Client
49+
dialer = proxy.Direct
4650
)
4751

4852
func init() {
@@ -54,6 +58,7 @@ func init() {
5458
}
5559
}
5660
RootCmd.Flags().StringVarP(&dmsgDisc, "dmsg-disc", "c", dmsgDisc, "dmsg discovery url")
61+
RootCmd.Flags().StringVarP(&proxyAddr, "proxy", "p", "", "connect to dmsg via proxy (i.e. '127.0.0.1:1080')")
5762
RootCmd.Flags().IntVarP(&dmsgSessions, "sess", "e", 1, "number of dmsg servers to connect to")
5863
RootCmd.Flags().StringVarP(&logLvl, "loglvl", "l", "fatal", "[ debug | warn | error | fatal | panic | trace | info ]\033[0m")
5964
RootCmd.Flags().StringVarP(&dmsgcurlData, "data", "d", "", "dmsghttp POST data")
@@ -102,6 +107,23 @@ DMSG curl utility`,
102107
ctx, cancel := cmdutil.SignalContext(context.Background(), dmsgcurlLog)
103108
defer cancel()
104109

110+
httpClient = &http.Client{}
111+
112+
if proxyAddr != "" {
113+
// Use SOCKS5 proxy dialer if specified
114+
dialer, err := proxy.SOCKS5("tcp", proxyAddr, nil, proxy.Direct)
115+
if err != nil {
116+
log.Fatalf("Error creating SOCKS5 dialer: %v", err)
117+
}
118+
transport := &http.Transport{
119+
Dial: dialer.Dial,
120+
}
121+
httpClient = &http.Client{
122+
Transport: transport,
123+
}
124+
ctx = context.WithValue(context.Background(), "socks5_proxy", proxyAddr) //nolint
125+
}
126+
105127
pk, err := sk.PubKey()
106128
if err != nil {
107129
pk, sk = cipher.GenerateKeyPair()
@@ -260,7 +282,7 @@ func parseOutputFile(output string, replace bool) (*os.File, error) {
260282
}
261283

262284
func startDmsg(ctx context.Context, pk cipher.PubKey, sk cipher.SecKey) (dmsgC *dmsg.Client, stop func(), err error) {
263-
dmsgC = dmsg.NewClient(pk, sk, disc.NewHTTP(dmsgDisc, &http.Client{}, dmsgcurlLog), &dmsg.Config{MinSessions: dmsgSessions})
285+
dmsgC = dmsg.NewClient(pk, sk, disc.NewHTTP(dmsgDisc, httpClient, dmsgcurlLog), &dmsg.Config{MinSessions: dmsgSessions})
264286
go dmsgC.Serve(context.Background())
265287

266288
stop = func() {

cmd/dmsgip/commands/dmsgip.go

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/skycoin/skywire/pkg/skywire-utilities/pkg/cmdutil"
1616
"github.com/skycoin/skywire/pkg/skywire-utilities/pkg/logging"
1717
"github.com/spf13/cobra"
18+
"golang.org/x/net/proxy"
1819

1920
"github.com/skycoin/dmsg/pkg/disc"
2021
"github.com/skycoin/dmsg/pkg/dmsg"
@@ -25,10 +26,13 @@ var (
2526
sk cipher.SecKey
2627
logLvl string
2728
dmsgServers []string
29+
proxyAddr string
30+
httpClient *http.Client
2831
)
2932

3033
func init() {
3134
RootCmd.Flags().StringVarP(&dmsgDisc, "dmsg-disc", "c", dmsgDisc, "dmsg discovery url\033[0m")
35+
RootCmd.Flags().StringVarP(&proxyAddr, "proxy", "p", "", "connect to dmsg via proxy (i.e. '127.0.0.1:1080')")
3236
RootCmd.Flags().StringVarP(&logLvl, "loglvl", "l", "fatal", "[ debug | warn | error | fatal | panic | trace | info ]\033[0m")
3337
if os.Getenv("DMSGIP_SK") != "" {
3438
sk.Set(os.Getenv("DMSGIP_SK")) //nolint
@@ -37,17 +41,17 @@ func init() {
3741
RootCmd.Flags().VarP(&sk, "sk", "s", "a random key is generated if unspecified\n\r\033[0m")
3842
}
3943

40-
// RootCmd containsa the root dmsgcurl command
44+
// RootCmd contains the root dmsgcurl command
4145
var RootCmd = &cobra.Command{
4246
Use: func() string {
4347
return strings.Split(filepath.Base(strings.ReplaceAll(strings.ReplaceAll(fmt.Sprintf("%v", os.Args), "[", ""), "]", "")), " ")[0]
4448
}(),
45-
Short: "DMSG ip utility",
49+
Short: "DMSG IP utility",
4650
Long: `
4751
┌┬┐┌┬┐┌─┐┌─┐ ┬┌─┐
4852
│││││└─┐│ ┬ │├─┘
4953
─┴┘┴ ┴└─┘└─┘ ┴┴
50-
DMSG ip utility`,
54+
DMSG IP utility`,
5155
SilenceErrors: true,
5256
SilenceUsage: true,
5357
DisableSuggestions: true,
@@ -71,20 +75,56 @@ DMSG ip utility`,
7175
srvs = append(srvs, pk)
7276
}
7377

74-
ctx, cancel := cmdutil.SignalContext(context.Background(), log)
75-
defer cancel()
76-
7778
pk, err := sk.PubKey()
7879
if err != nil {
7980
pk, sk = cipher.GenerateKeyPair()
8081
}
8182

82-
dmsgC, closeDmsg, err := startDmsg(ctx, log, pk, sk)
83-
if err != nil {
84-
log.WithError(err).Error("failed to start dmsg")
83+
ctx, cancel := cmdutil.SignalContext(context.Background(), log)
84+
defer cancel()
85+
86+
httpClient = &http.Client{}
87+
var dialer proxy.Dialer = proxy.Direct // Default dialer is direct connection
88+
89+
if proxyAddr != "" {
90+
// Use SOCKS5 proxy dialer if specified
91+
dialer, err = proxy.SOCKS5("tcp", proxyAddr, nil, proxy.Direct)
92+
if err != nil {
93+
log.Fatalf("Error creating SOCKS5 dialer: %v", err)
94+
}
95+
transport := &http.Transport{
96+
Dial: dialer.Dial,
97+
}
98+
httpClient = &http.Client{
99+
Transport: transport,
100+
}
101+
ctx = context.WithValue(context.Background(), "socks5_proxy", proxyAddr) //nolint
85102
}
86-
defer closeDmsg()
87103

104+
// Create DMSG client
105+
dmsgC := dmsg.NewClient(pk, sk, disc.NewHTTP(dmsgDisc, httpClient, log), &dmsg.Config{MinSessions: dmsg.DefaultMinSessions})
106+
go dmsgC.Serve(ctx) // Pass the context here
107+
108+
stop := func() {
109+
err := dmsgC.Close()
110+
log.WithError(err).Debug("Disconnected from dmsg network.")
111+
fmt.Printf("\n")
112+
}
113+
defer stop()
114+
115+
log.WithField("public_key", pk.String()).WithField("dmsg_disc", dmsgDisc).
116+
Debug("Connecting to dmsg network...")
117+
118+
select {
119+
case <-ctx.Done():
120+
stop()
121+
return ctx.Err()
122+
123+
case <-dmsgC.Ready():
124+
log.Debug("Dmsg network ready.")
125+
}
126+
127+
// Perform IP lookup using the context with the proxy dialer
88128
ip, err := dmsgC.LookupIP(ctx, srvs)
89129
if err != nil {
90130
log.WithError(err).Error("failed to lookup IP")
@@ -96,29 +136,6 @@ DMSG ip utility`,
96136
},
97137
}
98138

99-
func startDmsg(ctx context.Context, log *logging.Logger, pk cipher.PubKey, sk cipher.SecKey) (dmsgC *dmsg.Client, stop func(), err error) {
100-
dmsgC = dmsg.NewClient(pk, sk, disc.NewHTTP(dmsgDisc, &http.Client{}, log), &dmsg.Config{MinSessions: dmsg.DefaultMinSessions})
101-
go dmsgC.Serve(context.Background())
102-
103-
stop = func() {
104-
err := dmsgC.Close()
105-
log.WithError(err).Debug("Disconnected from dmsg network.")
106-
fmt.Printf("\n")
107-
}
108-
log.WithField("public_key", pk.String()).WithField("dmsg_disc", dmsgDisc).
109-
Debug("Connecting to dmsg network...")
110-
111-
select {
112-
case <-ctx.Done():
113-
stop()
114-
return nil, nil, ctx.Err()
115-
116-
case <-dmsgC.Ready():
117-
log.Debug("Dmsg network ready.")
118-
return dmsgC, stop, nil
119-
}
120-
}
121-
122139
// Execute executes root CLI command.
123140
func Execute() {
124141
if err := RootCmd.Execute(); err != nil {

cmd/dmsgweb/commands/dmsgweb.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,11 @@ var dmsgwebconffile = os.Getenv(dmsgwebenvname)
5858
func init() {
5959
RootCmd.Flags().StringVarP(&filterDomainSuffix, "filter", "f", ".dmsg", "domain suffix to filter")
6060
RootCmd.Flags().UintVarP(&proxyPort, "socks", "q", scriptExecUint("${PROXYPORT:-4445}", dmsgwebconffile), "port to serve the socks5 proxy")
61-
RootCmd.Flags().StringVarP(&addProxy, "proxy", "r", scriptExecString("${ADDPROXY}", dmsgwebconffile), "configure additional socks5 proxy for dmsgweb (i.e. 127.0.0.1:1080)")
61+
RootCmd.Flags().StringVarP(&addProxy, "addproxy", "r", scriptExecString("${ADDPROXY}", dmsgwebconffile), "configure additional socks5 proxy for dmsgweb (i.e. 127.0.0.1:1080)")
6262
RootCmd.Flags().UintSliceVarP(&webPort, "port", "p", scriptExecUintSlice("${WEBPORT[@]:-8080}", dmsgwebconffile), "port(s) to serve the web application")
6363
RootCmd.Flags().StringSliceVarP(&resolveDmsgAddr, "resolve", "t", scriptExecStringSlice("${RESOLVEPK[@]}", dmsgwebconffile), "resolve the specified dmsg address:port on the local port & disable proxy")
64-
RootCmd.Flags().StringVarP(&dmsgDisc, "dmsg-disc", "d", dmsg.DiscAddr(false), "dmsg discovery url")
64+
RootCmd.Flags().StringVarP(&dmsgDisc, "dmsg-disc", "d", dmsgDisc, "dmsg discovery url")
65+
RootCmd.Flags().StringVarP(&proxyAddr, "proxy", "x", "", "connect to dmsg via proxy (i.e. '127.0.0.1:1080')")
6566
RootCmd.Flags().IntVarP(&dmsgSessions, "sess", "e", scriptExecInt("${DMSGSESSIONS:-1}", dmsgwebconffile), "number of dmsg servers to connect to")
6667
RootCmd.Flags().BoolSliceVarP(&rawTCP, "rt", "c", scriptExecBoolSlice("${RAWTCP[@]:-false}", dmsgwebconffile), "proxy local port as raw TCP")
6768
RootCmd.Flags().StringVarP(&logLvl, "loglvl", "l", "", "[ debug | warn | error | fatal | panic | trace | info ]\033[0m")
@@ -203,7 +204,22 @@ dmsgweb conf file detected: ` + dmsgwebconffile
203204
}
204205
}
205206
}
206-
dmsgWebLog.Info("test")
207+
208+
if proxyAddr != "" {
209+
// Use SOCKS5 proxy dialer if specified
210+
dialer, err = proxy.SOCKS5("tcp", proxyAddr, nil, proxy.Direct)
211+
if err != nil {
212+
log.Fatalf("Error creating SOCKS5 dialer: %v", err)
213+
}
214+
transport := &http.Transport{
215+
Dial: dialer.Dial,
216+
}
217+
httpClient = &http.Client{
218+
Transport: transport,
219+
}
220+
ctx = context.WithValue(context.Background(), "socks5_proxy", proxyAddr) //nolint
221+
}
222+
207223
dmsgC, closeDmsg, err := startDmsg(ctx, pk, sk)
208224
if err != nil {
209225
dmsgWebLog.WithError(err).Fatal("failed to start dmsg")

cmd/dmsgweb/commands/dmsgwebsrv.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/skycoin/skywire/pkg/skywire-utilities/pkg/cmdutil"
2323
"github.com/skycoin/skywire/pkg/skywire-utilities/pkg/logging"
2424
"github.com/spf13/cobra"
25+
"golang.org/x/net/proxy"
2526

2627
"github.com/skycoin/dmsg/pkg/disc"
2728
dmsg "github.com/skycoin/dmsg/pkg/dmsg"
@@ -36,7 +37,8 @@ func init() {
3637
srvCmd.Flags().UintSliceVarP(&localPort, "lport", "l", scriptExecUintSlice("${LOCALPORT[@]:-8086}", dmsgwebsrvconffile), "local application http interface port(s)")
3738
srvCmd.Flags().UintSliceVarP(&dmsgPort, "dport", "d", scriptExecUintSlice("${DMSGPORT[@]:-80}", dmsgwebsrvconffile), "dmsg port(s) to serve")
3839
srvCmd.Flags().StringSliceVarP(&wl, "wl", "w", scriptExecStringSlice("${WHITELISTPKS[@]}", dmsgwebsrvconffile), "whitelisted keys for dmsg authenticated routes\r")
39-
srvCmd.Flags().StringVarP(&dmsgDisc, "dmsg-disc", "D", dmsg.DiscAddr(false), "dmsg discovery url")
40+
srvCmd.Flags().StringVarP(&dmsgDisc, "dmsg-disc", "D", dmsgDisc, "dmsg discovery url")
41+
srvCmd.Flags().StringVarP(&proxyAddr, "proxy", "x", "", "connect to dmsg via proxy (i.e. '127.0.0.1:1080')")
4042
srvCmd.Flags().IntVarP(&dmsgSess, "dsess", "e", scriptExecInt("${DMSGSESSIONS:-1}", dmsgwebsrvconffile), "dmsg sessions")
4143
srvCmd.Flags().BoolSliceVarP(&rawTCP, "rt", "c", scriptExecBoolSlice("${RAWTCP[@]:-false}", dmsgwebsrvconffile), "proxy local port as raw TCP")
4244
if os.Getenv("DMSGWEBSRVSK") != "" {
@@ -133,6 +135,21 @@ func server() {
133135
}
134136
}
135137

138+
if proxyAddr != "" {
139+
// Use SOCKS5 proxy dialer if specified
140+
dialer, err = proxy.SOCKS5("tcp", proxyAddr, nil, proxy.Direct)
141+
if err != nil {
142+
log.Fatalf("Error creating SOCKS5 dialer: %v", err)
143+
}
144+
transport := &http.Transport{
145+
Dial: dialer.Dial,
146+
}
147+
httpClient = &http.Client{
148+
Transport: transport,
149+
}
150+
ctx = context.WithValue(context.Background(), "socks5_proxy", proxyAddr) //nolint
151+
}
152+
136153
dmsgC := dmsg.NewClient(pk, sk, disc.NewHTTP(dmsgDisc, &http.Client{}, log), dmsg.DefaultConfig())
137154
defer func() {
138155
if err := dmsgC.Close(); err != nil {

cmd/dmsgweb/commands/root.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/gin-gonic/gin"
2020
"github.com/skycoin/skywire/pkg/skywire-utilities/pkg/cipher"
2121
"github.com/skycoin/skywire/pkg/skywire-utilities/pkg/logging"
22+
"golang.org/x/net/proxy"
2223

2324
"github.com/skycoin/dmsg/pkg/disc"
2425
dmsg "github.com/skycoin/dmsg/pkg/dmsg"
@@ -27,7 +28,8 @@ import (
2728
var (
2829
httpC http.Client
2930
dmsgC *dmsg.Client
30-
dmsgDisc string
31+
dmsgDisc = dmsg.DiscAddr(false)
32+
proxyAddr string
3133
dmsgSessions int
3234
dmsgAddr []string
3335
dialPK []cipher.PubKey
@@ -50,6 +52,8 @@ var (
5052
localPort []uint
5153
err error
5254
rawTCP []bool
55+
httpClient *http.Client
56+
dialer proxy.Dialer = proxy.Direct
5357
)
5458

5559
// Execute executes root CLI command.
@@ -60,8 +64,8 @@ func Execute() {
6064
}
6165

6266
func startDmsg(ctx context.Context, pk cipher.PubKey, sk cipher.SecKey) (dmsgC *dmsg.Client, stop func(), err error) {
63-
dmsgC = dmsg.NewClient(pk, sk, disc.NewHTTP(dmsgDisc, &http.Client{}, dmsgWebLog), &dmsg.Config{MinSessions: dmsgSessions})
64-
go dmsgC.Serve(context.Background())
67+
dmsgC = dmsg.NewClient(pk, sk, disc.NewHTTP(dmsgDisc, httpClient, dmsgWebLog), &dmsg.Config{MinSessions: dmsgSessions})
68+
go dmsgC.Serve(ctx)
6569

6670
stop = func() {
6771
err := dmsgC.Close()
@@ -83,6 +87,8 @@ func startDmsg(ctx context.Context, pk cipher.PubKey, sk cipher.SecKey) (dmsgC *
8387
}
8488
}
8589

90+
//TODO: these functions are more or less duplicated in several places - need to standardize and put in it's own library import in "github.com/skycoin/skywire/pkg/skywire-utilities/pkg/..."
91+
8692
func scriptExecString(s, envfile string) string {
8793
if runtime.GOOS == "windows" {
8894
var variable, defaultvalue string
@@ -133,6 +139,7 @@ func scriptExecString(s, envfile string) string {
133139
return ""
134140
}
135141
*/
142+
136143
func scriptExecStringSlice(s, envfile string) []string {
137144
if runtime.GOOS == "windows" {
138145
variable := s

pkg/dmsg/client.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/skycoin/skywire/pkg/skywire-utilities/pkg/cipher"
1414
"github.com/skycoin/skywire/pkg/skywire-utilities/pkg/logging"
1515
"github.com/skycoin/skywire/pkg/skywire-utilities/pkg/netutil"
16+
"golang.org/x/net/proxy"
1617

1718
"github.com/skycoin/dmsg/pkg/disc"
1819
)
@@ -502,6 +503,7 @@ func (ce *Client) dialSession(ctx context.Context, entry *disc.Entry) (cs Client
502503
ce.log.WithField("remote_pk", entry.Static).Debug("Dialing session...")
503504

504505
const network = "tcp"
506+
var conn net.Conn
505507

506508
// Trigger dial callback.
507509
if err := ce.conf.Callbacks.OnSessionDial(network, entry.Server.Address); err != nil {
@@ -514,9 +516,21 @@ func (ce *Client) dialSession(ctx context.Context, entry *disc.Entry) (cs Client
514516
}
515517
}()
516518

517-
conn, err := net.Dial(network, entry.Server.Address)
518-
if err != nil {
519-
return ClientSession{}, err
519+
proxyAddr, ok := ctx.Value("socks5_proxy").(string)
520+
if ok && proxyAddr != "" {
521+
socksDialer, err := proxy.SOCKS5("tcp", proxyAddr, nil, proxy.Direct)
522+
if err != nil {
523+
return ClientSession{}, fmt.Errorf("failed to create SOCKS5 dialer: %w", err)
524+
}
525+
conn, err = socksDialer.Dial(network, entry.Server.Address)
526+
if err != nil {
527+
return ClientSession{}, fmt.Errorf("failed to dial through SOCKS5 proxy: %w", err)
528+
}
529+
} else {
530+
conn, err = net.Dial(network, entry.Server.Address)
531+
if err != nil {
532+
return ClientSession{}, fmt.Errorf("failed to dial: %w", err)
533+
}
520534
}
521535

522536
dSes, err := makeClientSession(&ce.EntityCommon, ce.porter, conn, entry.Static)

0 commit comments

Comments
 (0)