블루투스를 이용해서 쉘에 접근할 수 있는 방법이 있다고 해서 정리해봄.


와이파이를 제대로 사용할 수 없는 등의 환경에 유용할 것 같은데.. 마냥 편하진 않다. 느리기도 하고...


0. bluetoothd 실행 옵션

bluez 5 부터 일부 커맨드라인 툴들이 deprecated 되었다.

hciconfig 는 바로 지원을 하는 것 같은데, SPP 추가를 위한 sdptool 이 작동하지 않음.


sudo vi /lib/systemd/system/bluetooth.service

ExecStart=/usr/lib/bluetooth/bluetoothd -C

데몬파일을 열어서 이렇게 수정해주자.(마지막에 -C 옵션 추가)



sudo systemctl daemon-reload
sudo systemctl restart bluetooth

그 후 블루투스 서비스를 재시작해주면 된다.



1. SP profile 추가

RPi 의 블루투스 프로파일에 SPP, Serial Port Profile 을 추가해야한다.


sudo sdptool add SP

위 명령어로 추가 가능. 재부팅, 서비스를 재시작 등을 하면 없어진다.

이 작업을 자동으로 해주고 싶으면,

블루투스 데몬 파일(/lib/systemd/system/bluetooth.service)에 아래와 같이 추가해줘도 됨.


ExecStartPost=/usr/bin/sdptool add SP

# 데몬 파일을 수정해줬으면 리붓하거나 reload & restart 해주자.
sudo systemctl daemon-reload
sudo systemctl restart bluetooth


추가가 되었는지는 아래와 같이 확인할 수 있다.


sudo sdptool browse local
(...)
Service Name: Serial Port
Service Description: COM Port
Service Provider: BlueZ
Service RecHandle: 0x10005
Service Class ID List:
  "Serial Port" (0x1101)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 1
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
Profile Descriptor List:
  "Serial Port" (0x1101)
    Version: 0x0100



2. 다른 장치에서 파이를 검색 가능하게 설정


# Page Scan & Inquiry Scan
sudo hciconfig hci0 piscan 
#OR
sudo btmgmt connectable on
sudo btmgmt discov yes

# Page Scan (기본값)
sudo hciconfig hci0 pscan
#OR
sudo btmgmt connectable on
sudo btmgmt discov no

# Scan 비활성화
sudo hciconfig hci0 noscan 
#OR
sudo btmgmt connectable off
sudo btmgmt discov no

Scan 을 활성화해두면 명령어로 재부팅 전까지 다른 장치의 블루투스 스캔에 응답할 수 있다.


Page Scan(connectable) 은 이미 서로 알고 있는, 즉 페어링된 적이 있는 기기와 연결하는 방식이고

Inquiry Scan(discoverable) 은 서로 모르는 기기가 연결하기 위한 방법이다.

(즉, 처음 연결이 필요할때만 Inquiry Scan 모드를 활성화해주면 된다.)


hciconfig hci0 명령어로 확인해보면 각 PSCAN ISCAN 키워드로 활성화 상태를 알려주고,

btmgmt info 명령어로 확인해본다면 current settings에 discoverable 이 있는지로 Inquiry Scan 활성화 여부를 확인할 수 있다.




3. RFCOMM 실행, 서비스화

RFCOMM 을 통해서 시리얼 연결을 터미널로 연결한다.



#rfcomm watch [dev] [channel] [cmd]
#    watch: listen 과 동일하지만, 자식 프로세스가 종료되거나 클라이언트와 연결이 끊길 경우 다시 listening 시작함.
sudo rfcomm watch hci0 1 getty rfcomm0 115200 vt100

이 명령어를 실행하면 다른 장치에서 블루투스로 파이에 연결했을때 터미널로 연결해준다.

특정 계정 자동 로그인을 해주고 싶다면 마지막에  -a <사용자> 를 추가해주자.

sudo rfcomm watch hci0 1 getty rfcomm0 115200 vt100 -a pi


이 명령어를 매번 실행해줄 수 없으므로, 이것도 데몬화한다.

/etc/systemd/system/rfcomm.service 파일을 아래와 같이 만들어 준다.



[Unit]
Description=RFCOMM service
After=bluetooth.service
Requires=bluetooth.service

[Service]
ExecStart=/usr/bin/rfcomm watch hci0 1 getty rfcomm0 115200 vt100

[Install]
WantedBy=multi-user.target


이후 아래 명령어로 활성화 해주면 끝.



sudo systemctl daemon-reload
sudo systemctl enable rfcomm # 자동실행 활성화
sudo systemctl start rfcomm # 시작



4. Mac 에서 연결

시스템 환경설정 - Bluetooth 에서 검색해서 연결할 수 있다.

일단 연결하면 기기 등록 후 잠깐 연결됨 상태이다가 바로 연결 안 됨 상태로 바뀔텐데 상관없음.



ls /dev/cu.*
(out)/dev/cu.MALS    /dev/cu.SOC    /dev/cu.Bluetooth-Incoming-Port
(out)/dev/cu.[hostname]-SerialPort


이렇게 /dev/cu.[hostname]-SerialPort 장치가 추가되어 있다. 추가가 안되어있다면 SP profile 이 제대로 추가가 안된 상태임.


이 장치를 열면 되는데, screen 으로 열 수 있다.


screen /dev/cu.[hostname]-SerialPort 115200


왜 그런건진 잘 모르겠는데, 이 상태에선 일부 출력(ssh 로그인이라던가..)이 client 의 쉘이 아니라, rfcomm을 실행한 쉘에 출력이 된다.

hyphen 옵션을 주고 다시 로그인해주면 해결됨.

su pi -


윈도우 사이즈도 제대로 반영이 안된다는 것 같은데, 이 경우에는 ssh localhost 로 해결된다고.



5. 다른 장치에서 연결

알아서 블루투스 시리얼 연결을 시도해보자... 일반적으로 많이 하는 SPP 연결방법과 동일해서 레퍼런스가 많을 듯.


윈도우는 모르겠고, 안드로이드에서는 관련 앱이 많을 것이고, iOS 에서는 안되는 것으로 안다.


SPP 말고 다른 프로파일로 어찌 만들어본다면 가능할 것 같긴 한데.. 일단 나는 맥에서만 연결이 되면 되기 때문에 나머진 생략.


참고

https://www.reddit.com/r/raspberry_pi/comments/6nchaj/guide_how_to_establish_bluetooth_serial/

TLS 1.0 은 이제 보안 정책으로 사용이 금지되어 있다.

그래서 기술적으로는 구현이 되어있음에도 불구하고, 브라우저나 각종 라이브러리로 사용을 하려고 하면 오류가 난다.



크롬 기준 이러한 사이트에 접속하려고 하면


The connection to this site uses 

TLS 1.0 (an obsolete protocol), 

RSA (an obsolete key exchange),

3DES_EDE_CBC with HMAC-SHA1 (an obsolete cipher).


이런 메시지를 내면서 접속을 불허한다.




이런 사이트에 대해 Python 을 사용하여 요청을 보낼때 이를 굳이 우회하는 방법.


나의 경우 requests 라이브러리를 사용했는데, urllib3 라이브러리를 사용한다면 동일하다.

urllib3.util.ssl_.DEFAULT_CIPHERS 에 'DES-CBC3-SHA' 을 추가해주면 됨.

콜론으로 구분되기 때문에



urllib3.util.ssl_.DEFAULT_CIPHERS += ':DES-CBC3-SHA'


이렇게 작성해주면 된다.

(DES-CBC3-SHA 과 3DES_EDE_CBC 은 명명법만 다르지 같다고 한다.)


requests 라이브러리를 쓴다면

requests.packages.urllib3 로 임포트 되어 있으니 여기다 해줘도 됨(혹은 여기다가 해줘야만 할 수도?)



requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':DES-CBC3-SHA'


이래도 안되는 경우가 있는데, OpenSSL 문제인 것 같다.

안되는 시스템에서 

$ curl --sslv3 주소

을 해봤을 때,

curl: (4) OpenSSL was built without SSLv3 support

같은 오류가 나온다면 v3을 지원하는 버전으로 재컴파일 하거나 설치해주도록 하자.


Trivial

requests 기준으로 인증서 오류도 날테니 요청을 보낼때 verify=False 인자도 추가해주자.



그리고 이러면 또 warning 이 매번 출력되는데, 아래와 같은 방법으로 비활성화 할 수 있다.

똑같은 코드지만, 상황에 맞게 복붙해서 사용하자.


# urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# requests
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)


참고

https://stackoverflow.com/questions/50707974/force-tls-1-0-connection-with-requests?noredirect=1&lq=1

https://stackoverflow.com/questions/27981545/suppress-insecurerequestwarning-unverified-https-request-is-being-made-in-pytho

나도 잠깐 고생한 적이 있었는데, 원인도 모르고 고생하다 나에게 물어오는 사람이 종종 생겨서,

혹시나 이 글이 검색에 걸려 도움을 받는 사람이 있을까 싶어 남겨본다.


통신사에서 제공하는 무료와이파이나 군부대 사지방 인터넷 등에서 웹서핑을 하면, 대부분의 사이트는 접속이 잘 되지만 특정 서비스들이 안되는 경우가 종종 발생한다.


특정 사이트 자체가 접속이 안되거나,

사이트 접속이 되긴 하는데 특정 기능이 작동을 안하거나,

특정 프로그램이 제대로된 작동을 못하거나.



이 문제들은 모두 공용 와이파이의 보안정책 때문인데, 정확히 확인해보진 않았지만 대충 80/443 포트를 제외하고 IN/OUT 을 다 막는다고 생각하면 된다. (dynamic port 대역은 남겨두려나?)


그래서 간단하게로는 :8080 이라던가, :8888 이라던가, :8443 등등 다른 포트 위에 돌아가는 페이지에 접속을 할 수 없거나,

5900 포트를 사용하는 vnc 등에 접속을 할 수 없다.


우리학교 포탈 시스템이 해당되고, 예전엔 KT 도 그랬던 것 같은데 지금은 아닌 듯.



해결법은 서비스 제공자에게 80/443 포트를 사용하여 서비스 하도록 요청하거나,

공용 와이파이의 정책을 완화해주도록 요청해야할텐데, 둘 다 아무래도 현실성이 떨어지겠지?


그냥 이런 구린 와이파이를 안쓰는게 제일 좋겠지만,

어쩔 수 없다면 80,443 포트를 사용하는 프록시나 openVPN 을 사용하는게 그나마 가능한 해결책일 것 같다.



이런 문제 때문에서인지, 카톡 같은 애들은 소켓을 열 때 80, 443 포트도 후보군에 있다.

서비스를 개발, 제공한다면 고려해보면 좋은 지점.

+ Recent posts