お世話になっております。
環境は、Windows XP(Or Windows 2000)、
VB6.0 SP6 + BASP21をインストールした端末で開発・運用をしています。
過去ログを調べ、遠隔サーバにあるファイルをFTPで取得する為には
BASP21を使うと開発が楽という記事を見かけました。
しかし、Telnetを複数回ネスト
(telnetにログインした後別のサーバにtelnetログインする)といった方法や
telnetにログインした後別のサーバにFTPでログイン、ファイルを取得する。という処理を行う場合等のサンプルは得られませんでした。
っとすると、
VB6.0で、telnetを複数ネストした処理を行う場合などは
GUI画面上で入力された情報から、batファイルを出力し、
実行させる方法しか思いつかないのですが、
途中経過の表等が出来ないなどの問題がある為、
出来れば他の方法を取りたいのですが、
こういった処理を行うことはVBでは無理なのでしょうか?
参考となる情報がありましたら、些細なことでもかまいませんので
返信いただきたいと思います。
telnetで接続できるサーバに接続してそこからFTPでいきたいということなのでしょうか。
サーバ自体そもそも外部へアクセスが許可されているならwinsockを使えばできるはずですが
>VB6.0で、telnetを複数ネストした処理を行う場合などは
>GUI画面上で入力された情報から、batファイルを出力し、
>実行させる方法しか思いつかないのですが、
ここらへんの処理を書いておかれると
みなさん返答しやすいかとおもいます。
>telnetで接続できるサーバに接続してそこからFTPでいきたいということなのでしょうか。
はい、イメージでは
Winows端末(Windows) - 中間サーバA - 中間サーバB - 装置A(Linux)
となり、FTPサービス、Telnetサービスが起動しています。
最終的な目標は、装置Aからログファイルを取得する。
ですが、その装置Aは操作端末(Windows XP)から直接FTPで覗くことは出来なく中間サーバを経由(telnet・FTPで)する必要があります。
昨日、私の考えていた
>GUI画面上で入力された情報から、batファイルを出力し、
というのは、
Windows標準で搭載されているコマンドプロンプトから
c:\ >telnet 127.0.0.1[=IP-Address] と入力すると、
「Microsoft Telnetクライアント」が起動しますが、
これを利用し、VBから、Telnet接続、FTP処理できないか?
と考えてました。
コマンドプロンプトで出来るならば、
Batファイルでも出来るのではないか?という安直な意識がありました。
現在の進捗としましては、
Batファイル化(※)したのですが、TelNet...の処理を実行後(1)、
手動でExitするまで次の処理(2)を受け付けないのが解り、早くも
Batファイルを利用しての接続をあきらめなければいけないのか?
っと思っているところです。
(telnet /? などを調べてもヘルプサポートされていないため)
(※)バッチファイルの中身
Call Telnet 127.0.0.1 ・・・(1)
Call USERNAME ・・・(2)
Call PASSWORD
長々と申し訳ないです。
Batファイルでダメ(見切りが早いかもしれませんが)ならば、
代わりにテラタームマクロ(.ttl)を利用し、
同じこと(TELNET・FTPの処理を任せてしまう)が出来ないか?は、
今試行錯誤中のため、その結果は今は出せていないです。
中間サーバが二つあるので
カスケード接続ができないとダメなんではないでしょうか?
ひとつであれば、過去ログかなんかにないでしょうか?
winsockのconnectedあたりでプロトコルにあった処理をするような。
中間A->中間B
というのがセキュリティ的に?な感じです。
'参考資料
RFC 854
RFC 959
ヤマ@文系 さん 再びのアドバイス、本当にありがとうございます。
Winsockコントロールは使ったことがなかったので、
何とか楽する
(コマンドプロンプトやテラタームのウィンドウハンドル?を
取ってメッセージの送信で簡潔させるetc)ようと考えていましたが・・・。
まずは慌てず、一歩一歩、
Winsockコントロールの使用例と紹介いただいた、
RFCをググりながらちょっとづつ進めていこうかと思います。
こちらもwinsockとか書いてしまいましたが、
inetコントロール(wininet)だとproxyを超えられない可能性があります。
http://support.microsoft.com/default.aspx?scid=kb;ja;409931
telnetの標準入出力がとれればいいのですが・・
とれないのは
セキュリティを考えてなのかも
しれませんね
ヤマ@文系 さん、あん さん夜分に恐れ入ります
今はテラタームを使って人が
手打ちでコマンドを入力し、ログ取得をしており
ツール化出来ないか?
という要望のため、全く意識出来て無かったですが
プロキシの件は要考慮ですね。
ご指摘ありがとうございます。
社内で仮の中間サーバを用意して
検討(動かしながら調査)している段階ですので実際は
プロキシサーバ越えの検討は後回しになってしまうかもしれませんが・・・。
2重のテルネットが可能か?を優先しているため
今週末までもう少し調査しながらハマってみます。
サンプルソースなど示せず申し訳有りません。
ちょこちょこ悩みながらなので掲示できるレベルのもの
になれば掲示します。
お世話になっております。
貴重なアドバイスを元に、2重テルネットの実装が出来ましたので、
後学のためになるか解らないのですが、フィードバックいたします。
前準備'フォームモジュールに
テキストボックス 4つ
コマンドボタン 2つ
Winsockコントロール 1つ貼り付けます。
'===以下ソースコード
Private Sub Command1_Click()
With Winsock1
If .State = sckClosed Then
.RemoteHost = Text1.Text ' 接続ホスト名
.RemotePort = Text2.Text ' 接続ポート番号
.Protocol = sckTCPProtocol ' 接続プロトコル
.Connect
End If
End With
End Sub
Private Sub Winsock1_Connect()
MsgBox "接続しました" & vbCrLf & _
Winsock1.RemoteHost & vbCrLf & _
Winsock1.RemotePort
Do
Call Wait
If telnetInfo_flg = True Then
Exit Do
End If
Call SetTelnetOption
Loop
Call TelnetLogin
End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Dim LngCnt As Long ' 汎用カウンタ
Text3.Text = ""
ReceveInfo_flg = True
' データの受信
ReDim bytReceiveData(bytesTotal - 1)
Winsock1.GetData bytReceiveData, vbArray + vbByte, bytesTotal
For LngCnt = 0 To UBound(bytReceiveData)
Text5.Text = Text5.Text & "," & Hex(bytReceiveData(LngCnt))
Next LngCnt
Debug.Print "ReservData:" & Text5.Text
ReceveInfo_flg = False
End Sub
Public Function Wait() As Boolean
Do
DoEvents
Sleep 500 ' 500ミリ秒処理をとめる
If ReceveInfo_flg = False Then ' 受信待ちになったら処理を抜ける
Exit Do
ElseIf Winsock1.State = sckClosed Then
Exit Do
End If
Loop
End Function
Public Sub SetTelnetOption()
Dim LngCnt As Long ' 汎用カウンタ
Dim bytLogin(6) As Byte ' login: プロンプト
' login: 表示されているか確認
bytLogin(0) = &H6C ' [l]
bytLogin(1) = &H6F ' [o]
bytLogin(2) = &H67 ' [g]
bytLogin(3) = &H69 ' [i]
bytLogin(4) = &H6E ' [n]
bytLogin(5) = &H3A ' [:]
For LngCnt = 0 To UBound(bytReceiveData) - 6
If (bytReceiveData(LngCnt) = bytLogin(0)) And _
(bytReceiveData(LngCnt + 1) = bytLogin(1)) And _
(bytReceiveData(LngCnt + 2) = bytLogin(2)) And _
(bytReceiveData(LngCnt + 3) = bytLogin(3)) And _
(bytReceiveData(LngCnt + 4) = bytLogin(4)) And _
(bytReceiveData(LngCnt + 5) = bytLogin(5)) Then
telnetInfo_flg = True
Exit Sub
End If
Next LngCnt
Erase bytSendData
ReDim bytSendData(UBound(bytReceiveData))
LngCnt = 0
' データの送信
Do
bytSendData(LngCnt) = bytReceiveData(LngCnt)
If (LngCnt > UBound(bytReceiveData) - 1) Then Exit Do
If bytReceiveData(LngCnt) = OPT_COM Then
' http://www5e.biglobe.ne.jp/~aji/3min/55.html 参考
Select Case bytReceiveData(LngCnt + 1)
Case OPT_DO ' 相手にオプション使用を要求
bytSendData(LngCnt + 1) = OPT_WONT ' オプションを使用しない
Case OPT_WILL ' 自分がオプション使用を宣言
bytSendData(LngCnt + 1) = OPT_DONT ' オプションを許可しない
Case OPT_WONT ' 相手のオプション使用をやめさせる
bytSendData(LngCnt + 1) = OPT_WONT ' 自身のオプションを無効にする
Case OPT_DONT ' 自分のオプションの無効化を宣言
bytSendData(LngCnt + 1) = OPT_DONT ' 了解する
Case Else
bytSendData(LngCnt + 1) = bytReceiveData(LngCnt + 1)
End Select
LngCnt = LngCnt + 1
End If
LngCnt = LngCnt + 1
Loop
Winsock1.SendData bytSendData
Erase bytSendData
End Sub
Public Sub TelnetLogin()
Dim bytEcho(2) As Byte '
bytEcho(0) = &HFF ' Do ECHO
bytEcho(1) = &HFC
bytEcho(2) = &H1
Winsock1.SendData bytEcho
Call Wait
bytEcho(0) = &HFF ' WONT ECHO
bytEcho(1) = &HFE
bytEcho(2) = &H1
Winsock1.SendData bytEcho
Call Wait
Winsock1.SendData "kawai" & vbCrLf ' 中間サーバA ユーザID
Call Wait
Winsock1.SendData "kawai" & vbCrLf ' 中間サーバA パスワード
Call Wait
Winsock1.SendData "pwd" & vbCrLf ' コマンド発行
Call Wait
Winsock1.SendData "telnet IP-ADDRESS" & vbCrLf ' 2重テルネット開始
Call Wait
Call Wait
Winsock1.SendData "user" & vbCrLf ' 中間サーバB ユーザID
Call Wait
Call Wait
Winsock1.SendData "pass" & vbCrLf ' 中間サーバB パスワード
End Sub
'続いて標準モジュール
Option Explicit
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
' TELNET Command 定数
Public Const OPT_WILL As Byte = &HFB ' OPTION CODE( WILL )
Public Const OPT_WONT As Byte = &HFC ' OPTION CODE( WON'T )
Public Const OPT_DO As Byte = &HFD ' OPTION CODE( WILL )
Public Const OPT_DONT As Byte = &HFE ' OPTION CODE( WON'T )
Public Const OPT_COM As Byte = &HFF ' [Interpret as Command] コマンドとして解釈
Public bytReceiveData() As Byte
Public bytSendData() As Byte
です。
苦労した点ですが、
接続完了した
Private Sub Winsock1_Connect()
で接続の後に、すぐloginが表示されるか?というとそうではないことが
解り、様々なオプションを設定してやらないといけないようです。
この情報は、ヤマ@文系 さんから提供いただいたRFC、及び
http://www5e.biglobe.ne.jp/~aji/3min/55.htmlのサイトが参考
となりました。
上記ソースでは、全てのオプションを無効にして接続するよう
設定を行っています。
ただし、一つ目のテルネットが完了した後、
2つ目のテルネットはコマンド発行のみ
Winsock1.SendData "telnet IP-ADDRESS" & vbCrLf ' 2重テルネット開始
で住みました、おそらくですが、ftpも同様の手法で接続できるはずです。
また、あん さんが懸念しておりました。
テルネットでの応答内容の取得も、pwdコマンド発行のレスが
受信できました。
最後に。。。
このスレッドにアドバイスしていただいた皆様
また、返信いただかなくとも興味を持っていただいた皆様に感謝し
スレッドを閉じたいと思います。
ありがとうございました。
解決チェックがもれていました。
解決できてよかったですね!
SendData "telnet "
というところがミソですね。
感動しました!
このロジック使えます!
標準入出力できる対話型telnet作ってみようかな
そうすればvbsとかで自動実行できそうだ
>SendData "telnet "
>というところがミソですね。
はい、あのあと同様に
SendData "ftp "とやっても
ftp>
が帰ってきたのでftpも問題有りませんでした。
>感動しました!
>このロジック使えます!
あとはもう少し次のコマンド発行まで
時間指定ではなく応答メッセージを解析する。
テルネットオプションの設定を柔軟にする
など改良が必要ですが、実現できるか?
の検証を優先させたため、かなりこの部分は適当で恥ずかしいサンプルすが、。
あんさん やま@文系さんありがとうございます。
対話型のtelnet作ってみました VB.NET版です
Imports System.io
Imports System.Net
Imports System.Net.Sockets
Public Class TelnetClient
Public Const OPT_WILL As Byte = &HFB ' OPTION CODE( WILL )
Public Const OPT_WONT As Byte = &HFC ' OPTION CODE( WON'T )
Public Const OPT_DO As Byte = &HFD ' OPTION CODE( WILL )
Public Const OPT_DONT As Byte = &HFE ' OPTION CODE( WON'T )
Public Const OPT_COM As Byte = &HFF ' [Interpret as Command] コマンドとして解釈
Private _addr As String
Private _port As String
Private _user As String
Private _pass As String
Private _client As TcpClient
Private _ns As NetworkStream
Private _reader As BinaryReader
Private _writer As BinaryWriter
Public Sub New(ByVal addr, Optional ByVal port = 23)
_addr = addr
_port = port
End Sub
Public Sub Open()
_client = New TcpClient(_addr, _port)
_ns = _client.GetStream
_client.ReceiveTimeout = 100
End Sub
Public Sub Read(ByRef str As String)
Dim data() As Byte
Dim echo1() As Byte = {&HFF, &HFC, &H1}
Dim echo2() As Byte = {&HFF, &HFE, &H1}
Try
Read(data)
str = System.Text.Encoding.GetEncoding("Shift_JIS").GetString(data)
If str Like "*login*" Then
Write(echo1)
Write(echo2)
End If
Catch ex As Exception
Throw New ApplicationException("")
End Try
End Sub
Public Sub Read(ByRef data As Byte())
_reader = New BinaryReader(_ns)
_writer = New BinaryWriter(_ns)
Dim msi As New MemoryStream
Dim mso As New MemoryStream
Dim dat As Byte
Try
Do
dat = _reader.ReadByte
msi.WriteByte(dat)
mso.WriteByte(dat)
If dat = OPT_COM Then
dat = _reader.ReadByte
msi.WriteByte(dat)
Select Case dat
Case OPT_DO ' 相手にオプション使用を要求
mso.WriteByte(OPT_WONT) ' オプションを使用しない
Case OPT_WILL ' 自分がオプション使用を宣言
mso.WriteByte(OPT_DONT) ' オプションを許可しない
Case OPT_WONT ' 相手のオプション使用をやめさせる
mso.WriteByte(OPT_WONT) ' 自身のオプションを無効にする
Case OPT_DONT ' 自分のオプションの無効化を宣言
mso.WriteByte(OPT_DONT) ' 了解する
Case Else
mso.WriteByte(dat)
End Select
End If
Loop
Catch ex As System.Net.Sockets.SocketException
Debug.WriteLine(ex.ToString)
Throw New ApplicationException("")
Catch ex As System.IO.EndOfStreamException
Debug.WriteLine(ex.ToString)
Throw New ApplicationException("")
Catch ex As Exception
Debug.WriteLine(ex.ToString)
End Try
If mso.ToArray.Length > 0 AndAlso mso.ToArray.GetValue(0) = &HFF Then
Debug.WriteLine("mso = " & BitConverter.ToString(mso.ToArray))
_writer.Write(mso.ToArray)
_writer.Flush()
End If
If msi.ToArray.Length > 0 Then
Debug.WriteLine("msi = " & BitConverter.ToString(msi.ToArray))
End If
data = msi.ToArray
End Sub
Public Sub Write(ByVal str As String)
Dim data() As Byte
Dim echo1() As Byte = {&HFF, &HFC, &H1}
Dim echo2() As Byte = {&HFF, &HFE, &H1}
data = System.Text.Encoding.GetEncoding("Shift_JIS").GetBytes(str)
Write(data)
End Sub
Public Sub Write(ByVal data As Byte())
_writer = New BinaryWriter(_ns)
Dim mso As New MemoryStream
Try
mso.Write(data, 0, data.Length)
_writer.Write(mso.ToArray)
_writer.Flush()
Catch ex As System.Net.Sockets.SocketException
Debug.WriteLine(ex.ToString)
Throw New ApplicationException("")
Catch ex As System.IO.EndOfStreamException
Debug.WriteLine(ex.ToString)
Throw New ApplicationException("")
Catch ex As Exception
End Try
End Sub
End Class
続きです メイン
Module Module1
Sub Main()
Dim tel As New TelnetClient(System.Environment.GetCommandLineArgs(1))
Dim data As Byte()
Dim str As String
Dim stro As String
Dim flg As Boolean = False
Try
tel.Open()
Do
tel.Read(str)
Debug.WriteLine(str)
Console.Write(str)
stro = Console.ReadLine()
If stro <> "" Then
tel.Write(stro & vbCrLf)
End If
Loop
Catch ex As Exception
End Try
End Sub
End Module
短時間で、流石です。
対話型telnetを使用したVBScriptの例
Set objShell = WScript.CreateObject("WScript.Shell")
Set objExec = objShell.Exec("TelnetClient.exe localhost")
Do Until objExec.StdOut.AtEndOfStream
strLine = objExec.StdOut.ReadLine()
Wscript.StdOut.WriteLine strLine
If InStr(strLine,"login:") <> 0 Then
objExec.StdIn.WriteLine "user"
Wscript.StdOut.WriteLine "Administrator"
input = ""
Else
If InStr(strLine,"password:") <> 0 Then
objExec.StdIn.WriteLine "pass"
Wscript.StdOut.WriteLine"pass"
Else
If InStr(strLine,">") <> 0 and flg = 0 Then
objExec.StdIn.WriteLine "Dir"
Wscript.StdOut.WriteLine "Dir"
objExec.StdIn.WriteLine "exit"
Wscript.StdOut.WriteLine "exit"
flg = 1
Else
objExec.StdIn.WriteLine ""
End If
End If
End If
Loop
入出力を楽にするためメインちと修正・・
Module Module1
Sub Main()
Dim tel As New TelnetClient(System.Environment.GetCommandLineArgs(1))
Dim data As Byte()
Dim str As String
Dim stro As String
Dim flg As Boolean = False
Try
tel.Open()
Do
tel.Read(str)
Debug.WriteLine(str)
Console.WriteLine(str) 'ここ
stro = Console.ReadLine()
If stro <> "" Then
tel.Write(stro & vbCrLf)
End If
Loop
Catch ex As Exception
End Try
End Sub
End Module
ツイート | ![]() |