[Swift] vpn 연결 확인 iOS detect vpn NetworkCopySystemProxySettings
iOS vpn 연결 상태 확인
오늘은 iOS에서 VPN 연결 확인 방법을 알아보자
아이폰 설정 → VPN → VPN 상태에서 VPN의 연결상태를 알 수 있다
VPN연결 상태를 앱에서 가져올 수 있는 방법이 여러 가지 있는데,
그중 "시스템 프록시 설정 값을 파싱"하는 방법을 사용하여
VPN 연결 상태를 알아보자
CFNetworkCopySystemProxySettings
CFNetworkCopySystemProxySettings()는 무엇일까?
이름 그대로 시스템 프록시 설정 값을 파싱 하는 함수이다
Apple Developer Documentation을 살펴보자
https://developer.apple.com/documentation/cfnetwork/cfnetworkcopysystemproxysettings()
오늘 우리가 사용할 함수
func CFNetworkCopySystemProxySettings() -> Unmanaged<CFDictionary>?
CFNetworkCopySystemProxySettings
Returns a CFDictionary containing the current systemwide internet proxy settings.
The dictionary returned contains key-value pairs that represent the current internet proxy settings. The keys in this dictionary are defined in Global Proxy Settings Constants.
The caller is responsible for releasing the returned dictionary.
🌏 번역 🌏
CFNetworkCopySystemProxySettings는
현재 시스템 전체 인터넷 프록시 설정이 포함된 CFDictionary를 반환합니다.
반환된 사전에는 현재 인터넷 프록시 설정을 나타내는 키-값 쌍이 포함되어 있습니다. 이 사전의 키는 전역 프록시 설정 상수에 정의되어 있습니다.
호출자는 반환된 사전을 해제할 책임이 있습니다.
한마디로 해석하면
CFNetworkCopySystemProxySettings함수는 현재 시스템 전체 인터넷 프록시 설정을 Dictionary로 반환한다
이 함수의 반환값을 통해 프록시 설정 값을 알 수 있다.
반환된 Dictionary의 프록시 설정값을 파싱 하여 VPN 상태를 알아보자!
Chap1. SystemConfiguration 라이브러리 Import
CFNetworkCopySystemProxySettings() 함수를 사용하려는 Class에 SystemConfiguration를 import 한다
import SystemConfiguration
Apple Developer Documentation에서 SystemConfiguration을 살펴보면,
SystemConfiguration은 애플리케이션이 기기의 네트워크 구성 설정에 액세스 할 수 있도록 허용합니다. Wi-Fi 또는 셀 연결이 활성화되어 있는지 등 장치의 연결 가능성을 확인합니다.
VPN 외에도 네트워크 구성 설정 정보를 얻어올 수 있다.
Chap2. CFNetworkCopySystemProxySettings 함수로 네트워크 구성 확인
CFNetworkCopySystemProxySettings() 함수를 사용하여 네트워크 구성이 존재하는지 알아보자
guard let cfDict = CFNetworkCopySystemProxySettings() else {
print("Failed to get proxy settings")
return false
}
위 코드를 설명하면
CFNetworkCopySystemProxySettings()를 호출하여 네트워크 구성 요소가 존재하면 구성 요소 Dictionary를 반환하고,
없다면 false를 반환한다.
Chap3. 네트워크 구성 요소 분석
위에서 CFNetworkCopySystemProxySettings() 함수를 호출하여 return 받은 Dictionary 값을 분석하자
class CheckVpnStatus {
func isVPNConnected() -> Bool {
guard let cfDict = CFNetworkCopySystemProxySettings() else {
print("Failed to get proxy settings")
return false
}
let nsDict = cfDict.takeRetainedValue() as NSDictionary
print("Proxy settings: \(nsDict)")
guard let keys = nsDict["__SCOPED__"] as? NSDictionary else {
print("No __SCOPED__ key found in proxy settings")
return false
}
print("Scoped keys: \(keys.allKeys)")
for key in keys.allKeys as! [String] {
if key == "tap" || key == "tun" || key == "ppp" || key == "ipsec" || key == "ipsec0" || key.starts(with: "utun") {
print("VPN is connected via \(key)")
return true
}
}
print("No VPN connection detected")
return false
}
}
❌ VPN 연결되지 않은 경우
CFNetworkCopySystemProxySettings() 함수 return X → VPN 연결: false
Dictionary에 "__SCOPED__"가 존재하지 X → VPN 연결: false
"__SCOPED__"Key에서 "ppp", "tun", "ipsec", "ipsec0" 값 중 하나도 존재하지 X → VPN 연결: false
⭕️ VPN 연결된 경우
CFNetworkCopySystemProxySettings()의 Dictionary가 존재하며,
Dictionary에 "__SCOPED__"가 존재하며,
"__SCOPED__"Key에서 "ppp", "tun", "ipsec", "ipsec0" 값 중 하나도 존재하면 → VPN 연결: true
VPN이 연결되면 네트워크 구성 요소에서 "ppp", "tun", "ipsec", "ipsec0" 중 값이 하나라도 존재한다.
Chap4. 예제
위 내용을 활용해 버튼을 클릭하여 VPN 연결 상태를 확인하는 예제를 만들어보자
- CheckVpnStatus.Swift
//
// CheckVpnStatus.swift
// VpnStatus
//
// Created by hyeebin on 6/17/24.
//
import Foundation
import SystemConfiguration
class CheckVpnStatus {
func isVPNConnected() -> Bool {
guard let cfDict = CFNetworkCopySystemProxySettings() else {
print("Failed to get proxy settings")
return false
}
let nsDict = cfDict.takeRetainedValue() as NSDictionary
print("Proxy settings: \(nsDict)")
guard let keys = nsDict["__SCOPED__"] as? NSDictionary else {
print("No __SCOPED__ key found in proxy settings")
return false
}
print("Scoped keys: \(keys.allKeys)")
for key in keys.allKeys as! [String] {
if key == "tap" || key == "tun" || key == "ppp" || key == "ipsec" || key == "ipsec0" || key.starts(with: "utun") {
print("VPN is connected via \(key)")
return true
}
}
print("No VPN connection detected")
return false
}
}
- ViewController.Swift
//
// ViewController.swift
// VpnStatus
//
// Created by hyeebin on 6/17/24.
//
import UIKit
class ViewController: UIViewController {
lazy var lbResult: UILabel = {
let lbResult = UILabel()
lbResult.translatesAutoresizingMaskIntoConstraints = false
lbResult.text = "VPN 상태"
lbResult.numberOfLines = 0
lbResult.textAlignment = .center
lbResult.font = UIFont.systemFont(ofSize: 28)
return lbResult
}()
lazy var btnStatus: UIButton = {
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("VPN 상태 확인", for: .normal)
button.backgroundColor = .systemBlue
button.setTitleColor(.white, for: .normal)
button.layer.cornerRadius = 10
button.addTarget(self, action: #selector(clickStatus), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
addViews()
applyConstraints()
}
fileprivate func addViews() {
view.addSubview(lbResult)
view.addSubview(btnStatus)
}
fileprivate func applyConstraints() {
let lbResultConstraints = [
lbResult.centerXAnchor.constraint(equalTo: view.centerXAnchor),
lbResult.topAnchor.constraint(equalTo: view.topAnchor,constant: 300),
]
let btnStatusConstraints = [
btnStatus.topAnchor.constraint(equalTo: lbResult.bottomAnchor,constant: 60),
btnStatus.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -60),
btnStatus.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 60),
btnStatus.heightAnchor.constraint(equalToConstant: 50)
]
NSLayoutConstraint.activate(btnStatusConstraints)
NSLayoutConstraint.activate(lbResultConstraints)
}
@objc fileprivate func clickStatus() {
getVpnStatus()
}
func getVpnStatus() {
let checkVpnStatus = CheckVpnStatus()
let status = checkVpnStatus.isVPNConnected() ? "Connected" : "Not Connected"
DispatchQueue.main.async { [self] in
lbResult.text = "VPN 상태: \(status)"
}
}
}
✨ 결과 화면 ✨
VPN 상태 - Not Connected ❌
VPN 상태 - Connected ⭕️
VPN 연결 상태이면,
아이폰 상단에 VPN 아이콘이 표시된다!
VPN상태이고 VPN 상태: Connected라고 가져온다
👇 깃허브에서 전체 소스코드 보기 👇
https://github.com/hyeebin/vpnstatus-ios