@@ -13,6 +13,7 @@ import (
1313 "github.com/safing/portmaster/service/mgr"
1414 "github.com/safing/portmaster/service/netenv"
1515 "github.com/safing/portmaster/service/network"
16+ "github.com/safing/portmaster/service/network/netutils"
1617 "github.com/safing/portmaster/service/network/packet"
1718 "github.com/safing/portmaster/spn/hub"
1819)
@@ -43,6 +44,7 @@ type vpnConnectionInfo struct {
4344// and its current VPN connection status, used for providing context in firewall verdicts.
4445type clientStatus struct {
4546 serviceBinary string
47+ servicePort uint16
4648 vpnConnection vpnConnectionInfo // VPN server endpoint
4749 connectedInfo * ivpnclient.ConnectedResp // info about already established VPN connection, if any
4850}
@@ -133,14 +135,28 @@ func (i *InteropIvpn) connectIvpnClient(wc *mgr.WorkerCtx) error {
133135 notifWarnOldVersion .Store (nil )
134136 }
135137
136- ci := ivpnclient.ClientInfo {
137- Type : ivpnclient .ClientPortmaster ,
138- Name : "Portmaster" ,
139- Version : info .Version ()}
138+ servicePort , _ , err := ivpnclient .GetConnectionPortInfo ()
139+ if err != nil {
140+ return err
141+ }
142+ // Save ServicePort.
143+ status := * i .getStatus ()
144+ status .servicePort = uint16 (servicePort )
145+ i .setStatus (& status )
146+ // Now we know the service port, we can register the verdict handler
147+ // to allow accepting connections to the IVPN client service port while the client is connecting.
148+ // This is needed for case when Portmaster default action is to block unknown connections.
149+ i .owner .EnsureVerdictHandlerRegistered ()
140150
141151 // Create client.
142152 // Ignoring error here, since it is expected that the client may not be in running state
143- client , err := ivpnclient .NewClientAsRoot (nil , time .Second * 10 , ci )
153+ client , err := ivpnclient .NewClientAsRoot (
154+ nil ,
155+ time .Second * 10 ,
156+ ivpnclient.ClientInfo {
157+ Type : ivpnclient .ClientPortmaster ,
158+ Name : "Portmaster" ,
159+ Version : info .Version ()})
144160 if err != nil {
145161 return nil
146162 }
@@ -183,15 +199,12 @@ func (i *InteropIvpn) connectIvpnClient(wc *mgr.WorkerCtx) error {
183199 }
184200
185201 // Save ServiceBinary.
186- status : = * i .getStatus ()
202+ status = * i .getStatus ()
187203 status .serviceBinary = helloResp .ServiceBinary
188204 i .setStatus (& status )
189205
190206 // The status.vpnConnection must be already initialized (ConnectionStarting message already received).
191207 i .setFirstTryDone ()
192- // Notify owner that we can now provide verdicts for firewall module
193- i .owner .EnsureVerdictHandlerRegistered ()
194-
195208 wc .Debug (fmt .Sprintf ("Connected to IVPN client %s" , helloResp .Version ))
196209
197210 // Show UI notification if not suppressed by user
@@ -270,6 +283,7 @@ func (i *InteropIvpn) VerdictHandler(conn *network.Connection) (verdict network.
270283 return network .VerdictUndecided , "" , false
271284 }
272285
286+ // Connection to remote VPN server
273287 if status .vpnConnection .dstPort != 0 {
274288 if conn .Entity .Port == status .vpnConnection .dstPort &&
275289 conn .Entity .Protocol == status .vpnConnection .protocol &&
@@ -283,6 +297,17 @@ func (i *InteropIvpn) VerdictHandler(conn *network.Connection) (verdict network.
283297 }
284298 }
285299
300+ // connections to IVPN service port
301+ if conn .LocalIPScope == netutils .HostLocal && conn .IPProtocol == packet .TCP {
302+ if conn .Inbound && conn .LocalPort == status .servicePort {
303+ return network .VerdictAccept , "IVPN Local Service connection" , true
304+ }
305+ if ! conn .Inbound && conn .Entity .Port == status .servicePort {
306+ return network .VerdictAccept , "IVPN Local Service connection" , true
307+ }
308+ }
309+
310+ // Connections from/to IVPN service (only when serviceBinary initialized)
286311 if status .serviceBinary != "" && conn .Process ().Path == status .serviceBinary {
287312 return network .VerdictAccept , "IVPN Service connection" , true
288313 }
0 commit comments